Nuevo en Symfony 5.1: Argumentos abstractos

En ocasiones, cuando defines servicios en tus aplicaciones Symfony, el valor de algunos argumentos no se puede definir en el archivo de configuración. El motivo es que esos valores solo están disponibles cuando se ejecuta la aplicación. Así que solo puedes inyectarlos desde un compiler pass o extensión de bundle.

En esos casos es habitual añadir un argumento vacío seguido de un comentario que explica que su valor será inyectado más adelante. Por ejemplo, el valor del segundo argumento del siguiente servicio es la lista de todos los directorios donde se guardan las plantillas Twig. Esta lista solo está disponible en tiempo de ejecución, ya que los bundles pueden añadir sus propios directorios:

<service id="twig.template_iterator" class="Symfony\Bundle\TwigBundle\TemplateIterator">
    <argument type="service" id="kernel" />
    <argument type="collection" /> <!-- Twig paths -->
    <argument>%twig.default_path%</argument>
</service>

Este otro servicio necesita el namespace principal de la aplicación, algo que es mejor calcula dinámicamente al ejecutar la aplicación en vez de obligar al usuario a configurar su valor manualmente:

<service id="maker.generator" class="Symfony\Bundle\MakerBundle\Generator">
    <argument type="service" id="maker.file_manager" />
    <argument /> <!-- root namespace -->
</service>

En Symfony 5.1 hemos mejorado esta configuración para reemplazar el "argumento vacío + comentario" por algo mejor: los argumentos abstractos. Se trata de argumentos cuyos valores se calculan en tiempo de ejecución mediante "compiler passes" o extensiones de bundles.

Así es como sería el anterior ejemplo usando argumentos abstractos:

<service id="maker.generator" class="Symfony\Bundle\MakerBundle\Generator">
    <argument type="service" id="maker.file_manager" />
    <argument type="abstract" key="$rootNamespace">defined in MakerPass</argument>
</service>

El valor de la opción key es el nombre del argumento en el constructor del servicio y el valor opcional encerrado entre <argument> ... </argument> es el comentario sobre el argumento. Si utilizas YAML para definir los servicios, esta es la sintaxis que debes utilizar:

maker.generator:
    class: Symfony\Bundle\MakerBundle\Generator
    arguments:
        $rootNamespace: !abstract defined in MakerPass

Y esta es la configuración necesaria cuando se utiliza PHP:

use Symfony\Bundle\MakerBundle\Generator;
use Symfony\Component\DependencyInjection\Argument\AbstractArgument;
 
$builder->register('maker.generator', Generator::class)
    ->setArgument('$rootNamespace', new AbstractArgument('defined in MakerPass'));

Si no inyectas el valor de un argumento abstracto en un "compiler pass" o extensión de bundle, verás el siguiente mensaje de error:

Argument "$rootNamespace" of service "maker.generator" is abstract
(defined in MakerPass), did you forget to define it?

Esta funcionalidad fue contribuida por Islam Israfilov en el pull request #35076.


Fuente: New in Symfony 5.1: Abstract service arguments

Comentarios

Publicada el

23 de abril de 2020

Etiquetas

Proyectos Symfony destacados

La plataforma de eCommerce 100% Symfony que rivaliza con Magento y PrestaShop. Ver más

Síguenos en @symfony_es para acceder a las últimas noticias.