forked from https://github.com/symfony/symfony
f99dfb0204
This PR was squashed before being merged into the 3.3-dev branch (closes #21708). Discussion ---------- [DI] Add and wire ServiceSubscriberInterface - aka explicit service locators | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | no test yet | Fixed tickets | #20658 | License | MIT | Doc PR | - This PR implements the second and missing part of #20658: it enables objects to declare their service dependencies in a similar way than we do for EventSubscribers: via a static method. Here is the interface and its current description: ```php namespace Symfony\Component\DependencyInjection; /** * A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method. * * The getSubscribedServices method returns an array of service types required by such instances, * optionally keyed by the service names used internally. Service types that start with an interrogation * mark "?" are optional, while the other ones are mandatory service dependencies. * * The injected service locators SHOULD NOT allow access to any other services not specified by the method. * * It is expected that ServiceSubscriber instances consume PSR-11-based service locators internally. * This interface does not dictate any injection method for these service locators, although constructor * injection is recommended. * * @author Nicolas Grekas <p@tchwork.com> */ interface ServiceSubscriberInterface { /** * Returns an array of service types required by such instances, optionally keyed by the service names used internally. * * For mandatory dependencies: * * * array('logger' => 'Psr\Log\LoggerInterface') means the objects use the "logger" name * internally to fetch a service which must implement Psr\Log\LoggerInterface. * * array('Psr\Log\LoggerInterface') is a shortcut for * * array('Psr\Log\LoggerInterface' => 'Psr\Log\LoggerInterface') * * otherwise: * * * array('logger' => '?Psr\Log\LoggerInterface') denotes an optional dependency * * array('?Psr\Log\LoggerInterface') is a shortcut for * * array('Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface') * * @return array The required service types, optionally keyed by service names */ public static function getSubscribedServices(); } ``` We could then have eg a controller-as-a-service implement this interface, and be auto or manually wired according to the return value of this method - using the "kernel.service_subscriber" tag to do so. eg: ```yaml services: App\Controller\FooController: arguments: [service_container] tags: - name: kernel.service_subscriber key: logger service: monolog.logger.foo_channel ``` The benefits are: - it keeps the lazy-behavior gained by service locators / container injection - it allows the referenced services to be made private from the pov of the main Symfony DIC - thus enables some compiler optimizations - it makes dependencies autowirable (while keeping manual wiring possible) - it does not add any strong coupling at the architecture level - and most importantly and contrary to regular container injection, *it makes dependencies explicit* - each classes declaring which services it consumes. Some might argue that: - it requires to be explicit - thus more verbose. Yet many others think it's a good thing - ie it's worth it. - some coupling happens at the dependency level, since you need to get the DI component to get the interface definition. This is something that the PHP-FIG could address at some point. Commits ------- |
||
---|---|---|
.composer | ||
.github | ||
src/Symfony | ||
.editorconfig | ||
.gitignore | ||
.php_cs.dist | ||
.travis.yml | ||
appveyor.yml | ||
CHANGELOG-3.0.md | ||
CHANGELOG-3.1.md | ||
CHANGELOG-3.2.md | ||
composer.json | ||
CONTRIBUTING.md | ||
CONTRIBUTORS.md | ||
LICENSE | ||
phpunit | ||
phpunit.xml.dist | ||
README.md | ||
UPGRADE-3.0.md | ||
UPGRADE-3.1.md | ||
UPGRADE-3.2.md | ||
UPGRADE-3.3.md | ||
UPGRADE-4.0.md |
Symfony is a PHP framework for web applications and a set of reusable PHP components. Symfony is used by thousands of web applications (including BlaBlaCar.com and Spotify.com) and most of the popular PHP projects (including Drupal and Magento).
Installation
- Install Symfony with Composer or with our own installer (see requirements details).
- Symfony follows the semantic versioning strictly, publishes "Long Term Support" (LTS) versions and has a release process that is predictable and business-friendly.
Documentation
- Read the Getting Started guide if you are new to Symfony.
- Try the Symfony Demo application to learn Symfony in practice.
- Master Symfony with the Guides and Tutorials, the Components docs and the Best Practices reference.
Community
- Join the Symfony Community and meet other members at the Symfony events.
- Get Symfony support on Stack Overflow, Slack, IRC, etc.
- Follow us on GitHub, Twitter and Facebook.
Contributing
Symfony is an Open Source, community-driven project with thousands of contributors. Join them contributing code or contributing documentation.
Security Issues
If you discover a security vulnerability within Symfony, please follow our disclosure procedure.
About Us
Symfony development is sponsored by SensioLabs, lead by the Symfony Core Team and supported by Symfony contributors.