8000 [Console] Command as service by gnugat · Pull Request #3621 · symfony/symfony-docs · GitHub
[go: up one dir, main page]

Skip to content

[Console] Command as service #3621

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Mar 24, 2014
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fixed @wouterj's feedback
  • Loading branch information
Loïc Chardonnet committed Mar 2, 2014
commit 6a7a25fa165b71a84c12350a3977eb549d4c3d2d
53 changes: 24 additions & 29 deletions components/console/commands_as_services.rst
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
.. index::
single: Console; Commands as Services

How to define Commands as Services
How to Define Commands as Services
==================================

.. versionadded:: 2.4
Support for registering commands in the service container was added in
Support for registering commands in the service container was introduced in
version 2.4.

By default, Symfony will take a look in the ``Command`` directory of your
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... of each bundle ...

bundles and automatically register your commands. For the ones implementing
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have to be careful because we're talking about the ContainerAwareCommand, not the actual ContainerAwareInterface.

If a command extends the ContainerAwareCommand, Symfony...

the ``ContainerAwareCommand`` interface, Symfony will even inject the container.

While making life easier, this default implementation has some drawbacks in some
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest adding this to the previous paragraph

situations:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... this has some limitations ...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I rephrased each bullet point below so that they all sound like limitations (not things that you will be able to do after registering as as service), since we mention limitations/drawbacks here.


* what if you want your command to be defined elsewhere than in the ``Command``
folder?
* what if you want to register conditionally your command, depending on the
* What if you want your command to be defined elsewhere than in the ``Command``
directory?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then you do this: https://github.com/doctrine/DoctrinePHPCRBundle/blob/master/DoctrinePHPCRBundle.php#L55

can we mention Bundle::registerCommands of the bundle for this, please? the important thing here i guess is thats in the bundle, not DI, so you can't use configuration to decide if you want to show the command (so the next point is whats really relevant).

* what if you want to conditionally register your command, depending on the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so the first What is uppercase and the later ones are lower case? is that correct?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. Usually later ones would be lowercase because of the semi-colon, but in this case there's question marks everywhere

Copy link
Member 8000

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All list items should just start with an uppercase letter imo (also when using a semi colon)

current environment or on the availability of some dependencies?
* what if you need to access dependencies before the ``setContainer`` is called
(for example in the ``configure`` method)?
* what if you need to access dependencies before the ``setContainer()`` is
called (for example in the ``configure()`` method)?
* what if you want to reuse a command many times, but with different
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better is to remove all the what ifs and just list use cases in which we want to do adhoc things

dependencies or parameters?

Expand All @@ -46,45 +45,41 @@ defining it with the ``console.command`` tag:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<service id="acme_hello.command.my_command"
class="Acme\HelloBundle\Command\MyCommand">
<tag name="console.command" />
</service>
<services>
<service id="acme_hello.command.my_command"
class="Acme\HelloBundle\Command\MyCommand">
<tag name="console.command" />
</service>
</services>
</container>

.. code-block:: php

// app/config/config.php

$container
->register('acme_hello.command.my_command', 'Acme\HelloBundle\Command\MyCommand')
->addTag('console.command')
;

Here are some use cases.

Use dependencies and parameters in configure
--------------------------------------------
Use Case: Using Dependencies and Parameters to Set Default Values for Options
-----------------------------------------------------------------------------

For example, imagine you want to provide a default value for the ``name``
argument. You could:
Imagine you want to provide a default value for the ``name``option. You could
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing a space between "name" and "option"

pass one of the following as the 5th argument of ``addOption()``:

* hard code a string and pass it as the 4th argument of ``addArgument``;
* allow the user to set the default value in the configuration;
* retrieve the default value from a service (a repository for example).
* an hardcoded string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • a hardcoded string;

* a value coming from the configuration (allows the user to change it easily);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear that we're really talking about a dependency injection parameter, so I propose:

  • a container parameter (e.g. something from parameters.yml);

* a value computed by a service (e.g. a repository).

With a ``ContainerAwareCommand`` you wouldn't be able to retrieve the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By extending ContainerAwareCommand, only the first is possible, because you can't
access the container inside the configure() method. Instead, inject any parameter or
service you need into the constructor. For example, suppose you have some NameRepository service that you'll use to get your default value:

configuration parameter, because the ``configure`` method is called in the
command's constructor. The only solution is to inject them through its
constructor:
configuration parameter, because the ``configure()`` method is called in the
constructor. The only solution is to inject them through it::
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe remove through it


<?php
// src/Acme/DemoBundle/Command/GreetCommand.php
namespace Acme\DemoBundle\Command;

use Acme\DemoBundle\Entity\NameRepository;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
Expand All @@ -105,13 +100,13 @@ constructor:
$this
->setName('demo:greet')
->setDescription('Greet someone')
->addArgument('name', InputArgument::OPTIONAL, 'Who do you want to greet?', $defaultName)
->addOption('name', '-n', InputOption::VALUE_REQUIRED, 'Who do you want to greet?', $defaultName)
;
}

protected function execute(InputInterface $input, OutputInterface $output)
{
$name = $input->getArgument('name');< A4B1 /td>
$name = $input->getOption('name');

$output->writeln($name);
}
Expand Down
1 change: 1 addition & 0 deletions components/console/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,7 @@ Learn More!
* :doc:`/components/console/usage`
* :doc:`/components/console/single_command_tool`
* :doc:`/components/console/events`
* :doc:`/components/console/commands_as_services`

.. _Packagist: https://packagist.org/packages/symfony/console
.. _ANSICON: https://github.com/adoxa/ansicon/releases
0