Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Personalizar un comando

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

¡Tenemos un nuevo comando de consola! Pero... todavía no hace mucho, aparte de imprimir un mensaje. Vamos a hacerlo más elegante.

Desplázate hasta la parte superior. Aquí es donde tenemos el nombre de nuestro comando, y también hay una descripción... que aparece al lado del comando. Permíteme cambiar la nuestra por

Un comando autoconsciente que puede hacer... sólo una cosa.

... lines 1 - 12
#[AsCommand(
... line 14
description: 'A self-aware command that can do... only one thing.',
)]
class TalkToMeCommand extends Command
{
... lines 19 - 43
}

Configurar los argumentos y las opciones

Nuestro comando se llama app:talk-to-me porque, cuando lo ejecutemos, quiero que sea posible pasar un nombre al comando -como Ryan- y que éste responda con "¡Hey Ryan!". Así que, literalmente, escribiremos bin/console app:talk-to-me ryan y nos responderá.

Cuando quieres pasar un valor a un comando, eso se conoce como argumento... y se configuran abajo en... el método configure(). Ya hay un argumento llamado arg1... así que vamos a cambiarlo por name.

Esta clave es completamente interna: nunca verás la palabra name cuando utilices este comando. Pero utilizaremos esta clave para leer el valor del argumento dentro de un minuto. También podemos dar una descripción al argumento y, si quieres, puedes hacerla obligatoria. Yo lo mantendré como opcional.

Lo siguiente que tenemos son las opciones. Son como los argumentos... excepto que empiezan con un -- cuando los utilizas. Quiero tener una bandera opcional en la que podamos decir --yell para que el comando grite nuestro nombre.

En este caso, el nombre de la opción, yell, es importante: utilizaremos este nombre cuando pasemos la opción en la línea de comandos para utilizarla. ElInputOption::VALUE_NONE significa que nuestra bandera será simplemente --yell y no--yell= algún valor. Si tu opción acepta un valor, lo cambiarías porVALUE_REQUIRED. Por último, dale una descripción.

... lines 1 - 16
class TalkToMeCommand extends Command
{
protected function configure(): void
{
$this
->addArgument('name', InputArgument::OPTIONAL, 'Your name')
->addOption('yell', null, InputOption::VALUE_NONE, 'Shall I yell?')
;
}
... lines 26 - 43
}

¡Precioso! Todavía no vamos a utilizar este argumento y esta opción... pero ya podemos volver a ejecutar nuestro comando con la opción --help:

php bin/console app:talk-to-me --help

Y... ¡impresionante! Vemos la descripción aquí arriba... junto con algunos detalles sobre cómo utilizar el argumento y la opción --yell.

Rellenando execute()

Cuando llamemos a nuestro comando, de forma muy sencilla, Symfony llamará a execute()... que es donde empieza la diversión. Dentro, podemos hacer lo que queramos. Nos pasa dos argumentos: $input y $output. Si quieres leer alguna entrada -como el argumentoname o la opción yell -, utiliza $input. Y si quieres dar salida a algo, utiliza $output.

Pero en Symfony, normalmente metemos estas dos cosas en otro objeto llamado SymfonyStyle. Esta clase de ayuda hace que la lectura y la salida sean más fáciles... y más elegantes.

Bien: empecemos por decir $name = $input->getArgument('name'). Si no tenemos un nombre, lo pondré por defecto en whoever you are. A continuación, lee la opción: $shouldYell = $input->getOption('yell'):

... lines 1 - 16
class TalkToMeCommand extends Command
{
... lines 19 - 26
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$name = $input->getArgument('name') ?: 'whoever you are';
$shouldYell = $input->getOption('yell');
... lines 32 - 40
}
}

Genial. Despejemos esto de aquí abajo y empecemos nuestro mensaje:$message = sprintf('Hey %s!', $name). Luego, si queremos gritar, ya sabes qué hacer: $message = strtoupper($message). Abajo, utiliza $io->success() y pon el mensaje ahí.

... lines 1 - 16
class TalkToMeCommand extends Command
{
... lines 19 - 26
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$name = $input->getArgument('name') ?: 'whoever you are';
$shouldYell = $input->getOption('yell');
$message = sprintf('Hey %s!', $name);
if ($shouldYell) {
$message = strtoupper($message);
}
$io->success($message);
return Command::SUCCESS;
}
}

Este es uno de los muchos métodos de ayuda de la clase SymfonyStyle que ayudan a dar formato a tu salida. También está $io->warning(), $io->note(), y varios más.

Vamos a probarlo. Gira y ejecuta:

php bin/console app:talk-to-me ryan

Y... ¡oh, hola! Si gritamos

php bin/console app:talk-to-me ryan --yell

¡TAMBIÉN FUNCIONA! Incluso podemos gritar a "quienquiera que sea":

php bin/console app:talk-to-me --yell

¡Impresionante! Pero vamos a volvernos más locos... autocableando un servicio y haciendo una pregunta de forma interactiva en la línea de comandos. Eso a continuación... ¡y es el último capítulo!

Leave a comment!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=8.1",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "knplabs/knp-time-bundle": "^1.18", // v1.19.0
        "symfony/asset": "6.1.*", // v6.1.0-RC1
        "symfony/console": "6.1.*", // v6.1.0-RC1
        "symfony/dotenv": "6.1.*", // v6.1.0-RC1
        "symfony/flex": "^2", // v2.1.8
        "symfony/framework-bundle": "6.1.*", // v6.1.0-RC1
        "symfony/http-client": "6.1.*", // v6.1.0-RC1
        "symfony/monolog-bundle": "^3.0", // v3.8.0
        "symfony/runtime": "6.1.*", // v6.1.0-RC1
        "symfony/twig-bundle": "6.1.*", // v6.1.0-RC1
        "symfony/ux-turbo": "^2.0", // v2.1.1
        "symfony/webpack-encore-bundle": "^1.13", // v1.14.1
        "symfony/yaml": "6.1.*", // v6.1.0-RC1
        "twig/extra-bundle": "^2.12|^3.0", // v3.4.0
        "twig/twig": "^2.12|^3.0" // v3.4.0
    },
    "require-dev": {
        "symfony/debug-bundle": "6.1.*", // v6.1.0-RC1
        "symfony/maker-bundle": "^1.41", // v1.42.0
        "symfony/stopwatch": "6.1.*", // v6.1.0-RC1
        "symfony/web-profiler-bundle": "6.1.*" // v6.1.0-RC1
    }
}