The new Symfony 3.3 Service Configuration Changes Explained
May 23, 2017 • Published by Ryan Weaver
tl;dr Symfony 3.3 comes with some big new service configuration features. We've explained them here: The Symfony 3.3 DI Container Changes Explained
In less than 2 weeks, Symfony 3.3 will be released. It comes with a lot of new stuff,
but there is one feature that stands out: the new service configuration. I am very
excited about these changes: they're designed to accelerate development, make Symfony
easier to learn and encourage best-practices (e.g. injecting specific dependencies instead
of using $container->get()
)... without sacrificing predictability and stability.
If you haven't seen it yet, the services.yml
file for a new Symfony 3.3 project will
look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
services:
# default configuration for services in *this* file
_defaults:
# automatically injects dependencies in your services
autowire: true
# automatically registers your services as commands, event subscribers, etc.
autoconfigure: true
# this means you cannot fetch services directly from the container via $container->get()
# if you need to do this, you can override this setting on individual services
public: false
# makes classes in src/AppBundle available to be used as services
# this creates a service per class whose id is the fully-qualified class name
AppBundle\:
resource: '../../src/AppBundle/*'
# you can exclude directories or files
# but if a service is unused, it's removed anyway
exclude: '../../src/AppBundle/{Entity,Repository}'
# controllers are imported separately to make sure they're public
# and have a tag that allows actions to type-hint services
AppBundle\Controller\:
resource: '../../src/AppBundle/Controller'
public: true
tags: ['controller.service_arguments']
There's a lot going on, including service auto-registration, autowiring and
auto-tagging (autoconfigure
).
Of course, these features are (and will always be) optional: you can upgrade your project to Symfony 3.3 without making any changes. But, I hope you'll give these new features a chance: I've already upgraded a large project and love them.
We've written an in-depth article explaining all of this further on the documentation: The Symfony 3.3 DI Container Changes Explained.
Try it, and let us know what you think!
Help the Symfony project!
As with any Open-Source project, contributing code or documentation is the most common way to help, but we also have a wide range of sponsoring opportunities.
Comments are closed.
To ensure that comments stay relevant, they are closed for old posts.
I've put together similar post, but much shorter and with before/after examples for those with lack of time :)
https://www.tomasvotruba.cz/blog/2017/05/07/how-to-refactor-to-new-dependency-injection-features-in-symfony-3-3/
GREAT question :). First, the services used here do not need to be public. That's actually true anywhere: if you have a private service, and need to use that service's id to configure something (e.g. a Twig global, a Guard authentication or the session handler_id (http://symfony.com/doc/current/session/sessions_directory.html)), you can use public or private services here. The only thing you *can't* do with a private service is access it from the container via $container->get().
Second, when you auto-register the services like in the new default configuration, the id of your services will match your class. So, in the link, your new config will look something like :
user_management: '@AppBundle\Service\UserManagement'
And yes, I must have missed that doc page - we've switched to showing class names as service ids in most places in the docs (though of course, both are valid still!)
Cheers!
Cheers!
# app/config/config_test.yml
services:
test.foo_manager: '@AppBundle\Service\FooManager'
This will create a public service called 'test.foo_manager'. You can use that in your test. And the rest of your configuration stays nice and clean :).
Cheers!
After a long time I could figure out that fully-qualified means e.g. AppBundle\Service\InvoiceGenerator. (Everything is in documentation... I'm a newbie)
My problem was that I was expecting to see my new Service class in the list of the container.
$ bin/console debug:container ProductService
The new class is never shown on this debug info.
The other thing that was not clear for me, is that from comments I was trying to add a Class in a Service folder and I could use it in the controller. Not so simple as it seems.
_defaults publics is false so I had an error by doing this:
$ps = $this->get('AppBundle\Service\ProductService');
my solution was change the service.yml a little bit:
AppBundle\:
resource: '../../src/AppBundle/*'
exclude: '../../src/AppBundle/{Entity,Repository,Service}'
and add this:
AppBundle\Service\:
resource: '../../src/AppBundle/Service'
public: true
tags: ['service.service_arguments']
I don't know if it is a good solution, as I said before, I'm starting to develop with this wonderful framework and I'm not sure of anything.
I made a comment for two reasons... someone give me a hint or help someone else on the same situation.
arguments: ["@mailer", "@translator.default", '%email.default.receiver%']
You can change to:
arguments:
$receiver: '%email.default.receiver%'