Cómo crear una orden de consola

La página Console de la sección de componentes (El componente Console) trata sobre cómo crear una orden de Consola. Este artículo trata sobre las diferencias cuando creas ordenes de consola en la plataforma Symfony2.

Registrando ordenes automáticamente

Para hacer que las ordenes de consola estén disponibles automáticamente en Symfony2, crea un directorio Command dentro de tu paquete y crea un archivo PHP con el sufijo Command.php para cada orden que deses proveer. Por ejemplo, si deseas ampliar el AcmeDemoBundle (disponible en la edición estándar de Symfony) para darte la bienvenida desde la línea de ordenes, crea el archivo GreetCommand.php y agrégale lo siguiente:

// 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('Greet someone')
            ->addArgument('name', InputArgument::OPTIONAL, 'Who do you want to greet?')
            ->addOption('yell', null, InputOption::VALUE_NONE, 'If set, the task will yell in uppercase letters')
        ;
    }

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

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

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

Ahora, automáticamente, esta orden estará disponible para funcionar:

$ app/console demo:greet Fabien

Obteniendo servicios del contenedor de servicios

Al usar Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand como la clase base para la orden (en lugar de la clase más básica Symfony\Component\Console\Command\Command), tienes acceso al contenedor de servicios. En otras palabras, tienes acceso a cualquier servicio configurado. Por ejemplo, fácilmente podrías extender la tarea para que sea traducible:

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!'));
    }
}

Probando ordenes

Cuando pruebes ordenes utilizadas como parte de la plataforma completa debes utilizar la Symfony\Bundle\FrameworkBundle\Console\Application en lugar de Symfony\Component\Console\Application:

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()
    {
        // simula el Kernel o crea uno dependiendo de tus necesidades
        $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());

        // ...
    }
}

Para poder utilizar plenamente el contenedor del servicios configurado en tus pruebas de consola puedes extender tu prueba de Symfony\Bundle\FrameworkBundle\Test\WebTestCase:

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());

        // ...
    }
}
Bifúrcame en GitHub