If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login Subscribe¡Felicidades, equipo! ¡Hemos terminado con lo más pesado de este tutorial! Así que es hora de dar la vuelta de la victoria. Vamos a instalar uno de mis bundles favoritos de Symfony: MakerBundle. Busca tu terminal y ejecuta:
composer require maker --dev
En este caso, estoy usando la bandera --dev
porque se trata de una utilidad de generación de código que sólo necesitamos localmente, no en producción.
Este bundle, por supuesto, proporciona servicios. Pero estos servicios no están pensados para que los utilicemos directamente. En su lugar, todos los servicios de este bundle potencian un montón de nuevos comandos de bin/console
. Ejecuta
php bin/console
y busca la sección make
. Ooh. Aquí hay un montón de cosas para configurar la seguridad, generar entidades de doctrina para la base de datos (lo que haremos en el siguiente tutorial), hacer un CRUD, y mucho más.
Vamos a probar una: ¿qué tal si intentamos construir nuestro propio y nuevo comando de consola personalizado que aparecerá en esta lista? Para ello, ejecuta:
php bin/console make:command
Esto te pedirá interactivamente el nombre del comando. Digamosapp:talk-to-me
. No es necesario, pero es bastante habitual anteponer a tus comandos personalizados el prefijo app:
. Y... ¡listo!
Eso ha creado exactamente un nuevo archivo: src/Command/TalkToMeCommand.php
. Vamos a abrirlo:
namespace App\Command; | |
use Symfony\Component\Console\Attribute\AsCommand; | |
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; | |
use Symfony\Component\Console\Style\SymfonyStyle; | |
( | |
name: 'app:talk-to-me', | |
description: 'Add a short description for your command', | |
) | |
class TalkToMeCommand extends Command | |
{ | |
protected function configure(): void | |
{ | |
$this | |
->addArgument('arg1', InputArgument::OPTIONAL, 'Argument description') | |
->addOption('option1', null, InputOption::VALUE_NONE, 'Option description') | |
; | |
} | |
protected function execute(InputInterface $input, OutputInterface $output): int | |
{ | |
$io = new SymfonyStyle($input, $output); | |
$arg1 = $input->getArgument('arg1'); | |
if ($arg1) { | |
$io->note(sprintf('You passed an argument: %s', $arg1)); | |
} | |
if ($input->getOption('option1')) { | |
// ... | |
} | |
$io->success('You have a new command! Now make it your own! Pass --help to see your options.'); | |
return Command::SUCCESS; | |
} | |
} |
¡Genial! ¡Arriba, puedes ver que el nombre y la descripción del comando se hacen en un atributo PHP! Luego, abajo en este método configure()
, del que hablaremos más en un minuto, podemos configurar los argumentos y opciones que se pueden pasar desde la línea de comandos.
Cuando ejecutemos el comando, se llamará a execute()
... donde podemos imprimir cosas en la pantalla o leer opciones y argumentos.
Quizá lo mejor de esta clase es que... ya funciona. ¡Compruébalo! De vuelta a tu terminal, ejecuta;
php bin/console app:talk-to-me
Y... ¡está vivo! No hace mucho, pero esta salida viene de aquí abajo. ¡Guau!
Pero espera... ¿cómo ha visto Symfony instantáneamente nuestra nueva clase Command
y ha sabido que debe empezar a utilizarla? ¿Es porque vive en el directorio src/Command/
... y Symfony escanea las clases que viven aquí? No Podríamos cambiar el nombre de este directorio aThereAreDefinitelyNoCommandsInHere
... y Symfony seguiría viendo el comando.
La forma en que esto funciona es mucho más genial. Abre config/services.yaml
y mira la sección _defaults
:
... lines 1 - 12 | |
services: | |
# default configuration for services in *this* file | |
_defaults: | |
autowire: true # Automatically injects dependencies in your services. | |
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. | |
... lines 18 - 32 |
Hemos hablado de lo que significa autowire: true
, pero no he explicado el propósito deautoconfigure: true
. Como está por debajo de _defaults
, la autoconfiguración está activa en todos nuestros servicios, incluido nuestro nuevo servicio TalkToMeCommand
. Cuando autoconfiguration
está activado, básicamente le dice a Symfony:
Oye, por favor, mira la clase base o la interfaz de cada servicio, y si parece que una clase debe ser un comando de consola... o un suscriptor de eventos... o cualquier otra clase que se enganche a una parte de Symfony, por favor, integra automáticamente integra el servicio en ese sistema. Bien, gracias. ¡Adiós!
¡Si! Symfony ve que nuestra clase extiende Command
y piensa:
Hmm, puede que no sea una IA autoconsciente... pero apuesto a que esto es un comando. Será mejor que se lo notifique al ¡> al sistema de la consola sobre ello!
Me encanta la autoconfiguración. Significa que podemos crear una clase PHP, extender cualquier clase base o implementar cualquier interfaz necesaria para la "cosa" que estamos construyendo, y... simplemente funcionará.
Internamente, si quieres conocer todos los detalles frikis, la autoconfiguración añade una etiqueta a tu servicio, como console.command
, que es lo que, en última instancia, ayuda a que el sistema de la consola se fije en él.
Muy bien, ahora que nuestro comando funciona, vamos a divertirnos un poco y a personalizarlo a continuación.
Hey @pasquale_pellicani!
I've added it to our screencast request list! Indeed, we have a tutorial about this, but it's showing its age.
Cheers!
// 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
}
}
Hi, it would be interesting to understand how to manage a custom bundle with symfony 6.x for medium and large sized projects it is convenient for organizing the code, because many things seem to have changed, thanks