The new Symfony 3.3 Service Configuration Changes Explained
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:
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!
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.
The new Symfony 3.3 Service Configuration Changes Explained symfony.com/index.php/blog/the-new-symfony-3-3-service-configuration-changes-explained
Tweet thisComments
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%'
Comments are closed.
To ensure that comments stay relevant, they are closed for old posts.
Tomáš Votruba said on May 23, 2017 at 09:55 #1
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/