As specific as possible
and
as general as needed
As a rule, a PHP object is a service if it is used globally in your application. A single Mailer service is used globally to send email messages whereas the many Message objects that it delivers are not services. Similarly, a Product object is not a service, but an object that persists Product objects to a database is a service.
# app/config/services.yml
parameters:
app.mailer.class: AppBundle\Mailer # stop it!
services:
app.mailer:
class: AppBundle\Mailer
arguments: [sendmail]# app/config/services.yml
imports:
- { resource: '@AcmeHelloBundle/Resources/config/common_services.yml' }
- { resource: '@AcmeHelloBundle/Resources/config/event_services.yml' }
- { resource: '@AcmeHelloBundle/Resources/config/security_services.yml' }
# ...class HelloController extends Controller
{
// ...
public function sendEmailAction()
{
// ...
$mailer = $this->get('app.mailer');
$mailer->send('ryan@foobar.net', ...);
}
}In this example, the controller extends Symfony's base Controller, which gives you access to the service container itself. You can then use the get method to locate and retrieve the app.mailer service from the service container. You can also define your controllers as services.
This is a bit more advanced and not necessary, but it allows you to inject only the services you need into your controller.
class HelloController
{
/** @var Mailer $mailer */
private $mailer;
/** @var Logger logger */
private $logger;
public function __construct(Mailer $mailer) {
$this->mailer = $mailer;
}
public function setLogger(Logger $logger) {
$this->logger = $logger;
}
public function sendEmailAction()
{
// ...
$this->mailer->send('ryan@foobar.net', ...);
if ($this->logger) {
$this->logger->info('Mail sent to ryan@foobar.net');
}
}
}# app/config/services.yml
services:
app.hello_controller:
class: AppBundle\Controller\HelloController
arguments: ["@app.mailer"]
calls:
- [setLogger, ["@logger"]]# app/config/services.yml
services:
third_party.service:
class: Some\Damn\Old\LibraryWithPublicProperties
properties:
mailer: '@my_mailer'namespace Some\Damn\Old;
class LibraryWithPublicProperties {
public $mailer;
// ...
}$ php app/console container:debug
[container] Public services
Service ID Scope Class name
annotation_reader container Doctrine\Common\Annotations\FileCacheReader
doctrine.orm.entity_manager n/a alias for "doctrine.orm.default_entity_manager"
logger container Symfony\Bridge\Monolog\Logger
request request
templating.helper.assets request Symfony\Component\Templating\Helper\CoreAssetsHelper# app/config/services.yml
### Symfony >= 2.8 ###
services:
app.some_not_shared_service:
class: ...
shared: false
### Symfony < 2.8 ###
services:
app.some_not_shared_service:
class: ...
scope: prototype# ...
services:
# ...
mail_manager:
abstract: true
calls:
- [setMailer, ["@my_mailer"]]
- [setEmailFormatter, ["@my_email_formatter"]]
newsletter_manager:
class: "NewsletterManager"
parent: mail_manager
greeting_card_manager:
class: "GreetingCardManager"
parent: mail_manager# app/config/services.yml
# Symfony >= 2.6
services:
app.repo.car:
class: 'AppBundle\Repository\CarRepository'
factory: [@doctrine.orm.entity_manager, 'getRepository']
arguments: ['AppBundle\Entity\Car']
# Symfony < 2.6
services:
app.repo.car:
class: 'AppBundle\Repository\CarRepository'
factory_class: doctrine.orm.entity_manager # no @ here
factory_method: 'getRepository'
arguments:
- 'AppBundle\Entity\Car'class TransportChain
{
private $transports;
public function __construct()
{
$this->transports = array();
}
public function addTransport(\Swift_Transport $transport)
{
$this->transports[] = $transport;
}
}services:
acme_mailer.transport_chain:
class: TransportChainservices:
acme_mailer.transport.smtp:
class: \Swift_SmtpTransport
arguments:
- '%mailer_host%'
tags:
- { name: acme_mailer.transport }
acme_mailer.transport.sendmail:
class: \Swift_SendmailTransport
tags:
- { name: acme_mailer.transport }class TransportCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (!$container->has('acme_mailer.transport_chain')) {
return;
}
$definition = $container->findDefinition(
'acme_mailer.transport_chain'
);
$taggedServices = $container->findTaggedServiceIds(
'acme_mailer.transport'
);
foreach ($taggedServices as $id => $tags) { // id = service-id
$definition->addMethodCall(
'addTransport',
array(new Reference($id))
);
}
}
}class AcmeMailerBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new CustomCompilerPass());
}
}class TransportChain
{
// ...
public function addTransport(\Swift_Transport $transport, $alias)
{
$this->transports[$alias] = $transport;
}
public function getTransport($alias)
{
if (array_key_exists($alias, $this->transports)) {
return $this->transports[$alias];
}
}
}services:
acme_mailer.transport.smtp:
class: \Swift_SmtpTransport
arguments:
- '%mailer_host%'
tags:
- { name: acme_mailer.transport, alias: foo }
acme_mailer.transport.sendmail:
class: \Swift_SendmailTransport
tags:
- { name: acme_mailer.transport, alias: bar }class TransportCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('acme_mailer.transport_chain')) {
return;
}
$definition = $container->getDefinition(
'acme_mailer.transport_chain'
);
$taggedServices = $container->findTaggedServiceIds(
'acme_mailer.transport'
);
foreach ($taggedServices as $id => $tags) { // != name
foreach ($tags as $attributes) {
$definition->addMethodCall(
'addTransport',
array(new Reference($id), $attributes["alias"])
);
}
}
}
}class HelloController
{
public function sendEmailAction(Request $request, $some, $thing)
{
// ...
$postData = $request->request;
}
}