Novedades en Symfony 7.4

Novedades en Symfony 7.4

  • Midiala Hernandez Alfonso
Comandos Invocables Mejorados
Symfony 7.4 introduce mejoras importantes en la forma de crear y ejecutar comandos invocables en la consola. 

Desde Symfony 7.3 es posible crear comandos como clases invocables, es decir, usando el método mágico __invoke() en lugar de execute().

Esto simplifica la sintaxis y elimina parte del código repetitivo que tradicionalmente se necesitaba en los comandos de consola.

Qué hay de nuevo en Symfony 7.4
En versiones anteriores, para definir un comando invocable era necesario declarar explícitamente el nombre del comando en el constructor o en una propiedad estática.

Con Symfony 7.4, ahora es posible definir el nombre directamente usando un atributo PHP, lo que hace el código más limpio y legible.

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;

#[AsCommand(
    name: 'app:greet',
    description: 'Saluda a un usuario'
)]
class GreetCommand extends Command
{
    public function __invoke(): int
    {
        // lógica del comando
        return self::SUCCESS;
    }
}


Esta nueva sintaxis también permite que Symfony detecte automáticamente si la clase del comando tiene un método __invoke(), de modo que ya no es necesario sobrescribir execute() manualmente. 

Ventajas
  • Menos código repetitivo.
  • Sintaxis más moderna y coherente con las prácticas actuales de PHP.
  • Mejor soporte para la inyección de dependencias directamente en el constructor o en el método __invoke().
  • Más flexibilidad al registrar y autoconfigurar comandos dentro del contenedor de servicios.

 Soporte de Enums en Comandos Invocables
 Symfony 7.4 permite usar Enums nativos de PHP en los atributos #[Argument] y #[Option].
Esto significa que los valores que el usuario introduce como texto se convierten automáticamente en el valor correspondiente del enum

enum CloudRegion: string
{
    case East = 'east';
    case West = 'west';
}

enum ServerSize: int
{
    case S = 1;
    case M = 2;
    case L = 3;
    case XL = 4;
}


#[AsCommand('app:add-server')]
class AddServerCommand
{
    public function __invoke(
        OutputInterface $output,
        #[Argument] CloudRegion $region,
        #[Option] ?ServerSize $size = null,
    ): int {
        $output->writeln($region->value);
        $output->writeln($size?->value ?? 'Sin valor');
        return Command::SUCCESS;
    }
}


 php bin/console app:add-server east --size=2

 Si el usuario introduce un valor no válido:

$ php bin/console app:add-server east-1
# Error:
# El valor "east-1" no es válido para el argumento "region".
# Valores permitidos: "east", "west". 

Nuevo atributo #[MapInput] en Symfony 7.4
Symfony 7.4 introduce el atributo #[MapInput], una mejora muy útil para los comandos invocables.
Este atributo permite inyectar automáticamente valores de entrada (argumentos y opciones) directamente en el método __invoke() o en cualquier otro método del comando, en lugar de tener que acceder manualmente a ellos a través de $input. 

Ejemplo básico
Antes, si querías usar los valores de entrada, tenías que escribir algo así:

public function __invoke(InputInterface $input, OutputInterface $output): int
{
    $name = $input->getArgument('name');
    $region = $input->getOption('region');
    // ...
}

 Con #[MapInput], puedes hacer lo siguiente: 

#[AsCommand('app:add-server')]
class AddServerCommand
{
    public function __invoke(
        #[MapInput] string $name,
        #[MapInput] ?string $region,
        OutputInterface $output
    ): int {
        $output->writeln(sprintf('Servidor "%s" agregado en la región "%s".', $name, $region));
        return Command::SUCCESS;
    }
}

 Symfony se encarga de mapear automáticamente los valores de los argumentos y opciones al tipo y nombre de cada parámetro del método. 

Cómo funciona
  • Symfony busca coincidencias entre los nombres de los parámetros del método y los argumentos/opciones definidos del comando.
  • El atributo #[MapInput] le indica al framework que debe inyectar el valor correspondiente automáticamente.
  • También funciona junto con #[Ask] y #[Interact], de modo que si falta algún valor, Symfony puede solicitarlo al usuario.

Comandos Invocables Interactivos
En Symfony 7.4 se introducen comandos invocables interactivos, una mejora que facilita la interacción con el usuario directamente desde los comandos de consola. 

Se añaden dos nuevos atributos:
  • #[Interact]: permite definir métodos que se ejecutan durante el modo interactivo.
     Antes era necesario sobrescribir interact(), pero ahora se puede usar cualquier método público anotado con #[Interact].

#[AsCommand('app:add-server')]
class AddServerCommand
{
    #[Interact]
    public function prompt(InputInterface $input, SymfonyStyle $io): void
    {
        if (!$input->getArgument('region')) {
            $input->setArgument('region', $io->ask('Introduce la región del servidor'));
        }
    }
}


#[Ask]: sirve para pedir de forma automática valores faltantes de argumentos u opciones, haciendo el código más simple. 

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Attribute\Ask;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Console\Input\InputInterface;

#[AsCommand('app:add-server')]
class AddServerCommand extends Command
{
    public function __construct(
        #[Ask('¿Cuál es el nombre del servidor?')]
        private string $name,

        #[Ask('¿En qué región se encuentra el servidor?')]
        private string $region,
    ) {}

    public function __invoke(SymfonyStyle $io, InputInterface $input): int
    {
        $io->success(sprintf('Servidor "%s" agregado en la región "%s".', $this->name, $this->region));
        return self::SUCCESS;
    }
}


Cómo funciona
  • Si el usuario ejecuta php bin/console app:add-server sin argumentos, Symfony detecta los atributos #[Ask] y automáticamente le hace las preguntas en la consola.
  • Las respuestas se asignan a las propiedades del comando ($name y $region) antes de ejecutar el método __invoke().
  • Si el usuario pasa los argumentos directamente (php bin/console app:add-server myserver eu-west), Symfony usa esos valores sin mostrar las preguntas.


  • Symfony
  • PHP
Yonel
05 de Nov de 2025

Hola, gracias por publicar este artículo en Español. Un detalle, al comienzo del artículo se menciona "Symfony 6.1", creo que debería ser "Symfony 7.3" clases invocables fueron implementadas. Un saludo hermano!

Deja un comentario: