Skip to content

Commit

Permalink
Fixed the section about getting services from a command
Browse files Browse the repository at this point in the history
  • Loading branch information
javiereguiluz committed May 29, 2014
1 parent bffe163 commit 0f3c218
Showing 1 changed file with 59 additions and 2 deletions.
61 changes: 59 additions & 2 deletions cookbook/console/console_command.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,27 @@ Getting Services from the Service Container
By using :class:`Symfony\\Bundle\\FrameworkBundle\\Command\\ContainerAwareCommand`
as the base class for the command (instead of the more basic
:class:`Symfony\\Component\\Console\\Command\\Command`), you have access to the
service container. In other words, you have access to any configured service.
For example, you could easily extend the task to be translatable::
service container. In other words, you have access to any configured service::

protected function execute(InputInterface $input, OutputInterface $output)
{
$name = $input->getArgument('name');
$logger = $this->getContainer()->get('logger');

$logger->info('Executing command for '.$name);
// ...
}

However, due to the `container scopes </cookbook/service_container/scopes>`_ this
code doesn't work for some services. For instance, if you try to get the ``request``
service or any other service related to it, you'll get the following error:

.. code-block:: text
You cannot create a service ("request") of an inactive scope ("request").
Consider the following example that uses the ``translator`` service to
translate some contents using a console command::

protected function execute(InputInterface $input, OutputInterface $output)
{
Expand All @@ -82,6 +101,44 @@ For example, you could easily extend the task to be translatable::
}
}

If you dig into the Translator component classes, you'll see that the ``request``
service is required to get the locale into which the contents are translated::

// vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php
public function getLocale()
{
if (null === $this->locale && $this->container->isScopeActive('request')
&& $this->container->has('request')) {
$this->locale = $this->container->get('request')->getLocale();
}

return $this->locale;
}

Therefore, when using the ``translator`` service inside a command, you'll get the
previous *"You cannot create a service of an inactive scope"* error message.
The solution in this case is as easy as setting the locale value explicitly
before translating contents::

protected function execute(InputInterface $input, OutputInterface $output)
{
$name = $input->getArgument('name');
$locale = $input->getArgument('locale');

$translator = $this->getContainer()->get('translator');
$translator->setLocale($locale);

if ($name) {
$output->writeln($translator->trans('Hello %name%!', array('%name%' => $name)));
} else {
$output->writeln($translator->trans('Hello!'));
}
}

However for other services the solution might be more complex. You may even need
to manually create a ``request`` service and then call the ``enterScope('request')``
and the ``set('request', $request)`` methods.

Testing Commands
----------------

Expand Down

0 comments on commit 0f3c218

Please sign in to comment.