New in Symfony 3.3: PSR-4 based Service Discovery

Contributed by
Nicolas Grekas Ryan Weaver
in #21289 and #22680.

Symfony 3.3 will introduce lots of features to simplify the way you work with services in your applications, such as simpler configuration and autoconfig. This article explains the last big feature related to Dependency Injection: PSR-4 based service discovery and registration.

The idea is to look for PHP classes in some given directories and register them as services if their namespaces meet the PSR-4 naming syntax. This feature is configured using the resource option, which accepts a directory path or a Glob expression to match multiple directories. Example:

services:
    App\:
        resource: ../src/{Controller,Command}
        # ...

This config looks for PHP files in the src/Controller/ and src/Command/ directories of the application, infers the PSR-4 class names from those files and uses class_exist() to check that they exist before registering those classes as Symfony services (using the class FQCN as the service id).

This feature is so convenient that Symfony Flex uses it by default in the app.yaml config file that will be used in Symfony 4 applications:

services:
    # ...

    # this creates a service per class whose id is the fully-qualified class name
    App\:
        resource: '../../src/{Command,Form,EventSubscriber,Twig,Security}'

    App\Controller\:
        resource: '../../src/Controller'
        public: true
        tags: ['controller.service_arguments']

If your application contains lots of directories, you can include all of them using a * value in the resource option and then use the exclude option to exclude some directories if needed:

services:
    # ...

    AppBundle\:
        # discover services in all AppBundle/ sub-directories...
        resource: '../../src/AppBundle/*'
        # ... except in those matching this Glob expression
        exclude: '../../src/AppBundle/{AppBundle.php,Entity}'

Comments

What about the dependencies of the services? Somehow it isn't clear to me, how the injection parameters are defined in this automatic scan - is autowiring turned on by default? What if the services use interfaces as a dependency?
Maybe it would be nice to mention the tiny details I'm asking about in the article as well.
@Martin, you just need to redefine your service.
@Martin yes, you may need some more config. Check the contents of the app.yaml file used by Symfony Flex: https://github.com/symfony/recipes/blob/master/symfony/framework-bundle/3.3/etc/packages/app.yaml
I love most of the work going on in Symfony at the moment, there's some great stuff in the pipeline for future version. However I'm not convinced these autowiring and FQCN-based service names changes are a wise idea. While it makes it easy to get up and running, understanding what is happening behind the scenes becomes quite confusing, then people are forced to learn the current way to define their services once things get too complex for the automatic methods to handle.

Can anyone explain to me the benefit of this change? Or is there a Github issue I could read? Genuine request.
awesome
Will this feature be in Symfony 3 certification questions?
I think it will break docker based structures that using Alpine Linux. Because Alpine doesn't support GLOB_BRACE since it is using musl libc instead of GNU libc.

https://bugs.php.net/bug.php?id=72095
http://ftp.grokbase.com/t/php/php-doc-bugs/164rneeqx3/php-bug-bug-72095-new-undefined-constant-glob-brace-while-doc-base-configure-php
https://github.com/zendframework/zend-stdlib/issues/58
Sorry, it seems this situation has already been handled. Thank you. https://github.com/symfony/symfony/pull/21289/files#diff-ad1ed76aba6a80df5a48dfa4585adcf3R115

Comments are closed.

To ensure that comments stay relevant, they are closed for old posts.