diff --git a/service_container.rst b/service_container.rst index 7b772f14626..c6365940e97 100644 --- a/service_container.rst +++ b/service_container.rst @@ -815,20 +815,35 @@ Public Versus Private Services From Symfony 4.0, every service defined is private by default. What does this mean? When a service **is** public, you can access it directly -from the container object, which is accessible from any controller that extends -``Controller``:: +from the container object, which can also be injected thanks to autowiring. +This is mostly useful when you want to fetch services lazily:: - use App\Service\MessageGenerator; + namespace App\Generator; - // ... - public function new() + use Psr\Container\ContainerInterface; + + class MessageGenerator { - // there IS a public "logger" service in the container - $logger = $this->container->get('logger'); + private $container; - // this will NOT work: MessageGenerator is a private service - $generator = $this->container->get(MessageGenerator::class); - } + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + public function generate(string $message, string $template = null, array $context = []): string + { + if ($template && $this->container->has('twig')) { + // there IS a public "twig" service in the container + $twig = $this->container->get('twig'); + + return $twig->render($template, $context + ['message' => $message]); + } + + // if no template is passed, the "twig" service will not be loaded + + // ... + } As a best practice, you should only create *private* services, which will happen automatically. And also, you should *not* use the ``$container->get()`` method to @@ -845,7 +860,7 @@ But, if you *do* need to make a service public, override the ``public`` setting: # ... same code as before # explicitly configure the service - App\Service\MessageGenerator: + Acme\PublicService: public: true .. code-block:: xml @@ -861,7 +876,7 @@ But, if you *do* need to make a service public, override the ``public`` setting: - + @@ -870,17 +885,22 @@ But, if you *do* need to make a service public, override the ``public`` setting: // config/services.php namespace Symfony\Component\DependencyInjection\Loader\Configurator; - use App\Service\MessageGenerator; + use Acme\PublicService; return function(ContainerConfigurator $configurator) { // ... same as code before // explicitly configure the service - $services->set(MessageGenerator::class) + $services->set(PublicService::class) ->public() ; }; +.. note:: + + Instead of injecting the container you should consider using a + :ref:`service locator ` instead. + .. _service-psr4-loader: Importing Many Services at once with resource diff --git a/service_container/service_subscribers_locators.rst b/service_container/service_subscribers_locators.rst index 5a12cf1c3e6..f777cabd135 100644 --- a/service_container/service_subscribers_locators.rst +++ b/service_container/service_subscribers_locators.rst @@ -1,6 +1,8 @@ .. index:: single: DependencyInjection; Service Subscribers +.. _service-locators: + Service Subscribers & Locators ==============================