Creative Commons License
This work is licensed under a
Creative Commons
Attribution-Share Alike 3.0
Unported License.

Master Symfony2 fundamentals

Be trained by SensioLabs experts (2 to 6 day sessions -- French or English).
trainings.sensiolabs.com

Symfony hosting done right

ServerGrove, outstanding support at the right price for your Symfony hosting needs.
servergrove.com

Discover the SensioLabs Support

Access to the SensioLabs Competency Center for an exclusive and tailor-made support on Symfony
sensiolabs.com

Come creare un comando di console

Come creare un comando di console

La pagina Console della sezione dei componenti (Il componente Console) spiega come creare un comando di console. Questa ricetta spiega invece le differenze nella creazione di comandi di console con il framework Symfony2.

Registrare comandi automaticamente

Per rendere disponibili automaticamente i comandi in Symfony2, creare una cartella Command nel proprio bundle e creare un file php, con suffisso Command.php, per ciascun comando che si vuole fornire. Per esempio, se si vuole estendere AcmeDemoBundle (disponibile nella Standard Edition di Symfony), per mandare un saluto dalla linea di comando, creare GreetCommand.php e aggiungervi il codice seguente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// src/Acme/DemoBundle/Command/GreetCommand.php
namespace Acme\DemoBundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class GreetCommand extends ContainerAwareCommand
{
    protected function configure()
    {
        $this
            ->setName('demo:greet')
            ->setDescription('Saluta qualcuno')
            ->addArgument('name', InputArgument::OPTIONAL, 'Chi vuoi salutare?')
            ->addOption('yell', null, InputOption::VALUE_NONE, 'Se impostato, urlerà in lettere maiuscole')
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $name = $input->getArgument('name');
        if ($name) {
            $text = 'Ciao '.$name;
        } else {
            $text = 'Ciao';
        }

        if ($input->getOption('yell')) {
            $text = strtoupper($text);
        }

        $output->writeln($text);
    }
}

Ora il comando sarà automaticamente disponibile:

1
$ app/console demo:greet Fabien

Getting Services from the Service Container

Usando ContainerAwareCommand come classe base per il comando (al posto della più basica Command), si ha accesso al contenitore di servizi. In altre parole, si ha accesso a qualsiasi servizio configurato. Per esempio, si può facilmente estendere il task per essere traducibile:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
protected function execute(InputInterface $input, OutputInterface $output)
{
    $name = $input->getArgument('name');
    $translator = $this->getContainer()->get('translator');
    if ($name) {
        $output->writeln($translator->trans('Hello %name%!', array('%name%' => $name)));
    } else {
        $output->writeln($translator->trans('Hello!'));
    }
}

Testare i comandi

Quando si testano i comandi usati come parte di un framework, andrebbe usata Application al posto di Application:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Acme\DemoBundle\Command\GreetCommand;

class ListCommandTest extends \PHPUnit_Framework_TestCase
{
    public function testExecute()
    {
        // fare un mock del Kernel o crearme uno, a seconda delle esigenze
        $application = new Application($kernel);
        $application->add(new GreetCommand());

        $command = $application->find('demo:greet');
        $commandTester = new CommandTester($command);
        $commandTester->execute(array('command' => $command->getName()));

        $this->assertRegExp('/.../', $commandTester->getDisplay());

        // ...
    }
}

Per poter usare il contenitore in modo completo per i test della console, si può estendere il test da SymfonyBundleFrameworkBundleTestWebTestCase:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Acme\DemoBundle\Command\GreetCommand;

class ListCommandTest extends WebTestCase
{
    public function testExecute()
    {
        $kernel = $this->createKernel();
        $kernel->boot();

        $application = new Application($kernel);
        $application->add(new GreetCommand());

        $command = $application->find('demo:greet');
        $commandTester = new CommandTester($command);
        $commandTester->execute(array('command' => $command->getName()));

        $this->assertRegExp('/.../', $commandTester->getDisplay());

        // ...
    }
}