Login to bookmark this video
Buy Access to Course
07.

Decorar un servicio con AsDecorator

|

Share this awesome video!

|

Keep on Learning!

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

Login Subscribe

En el capítulo anterior, utilizamos #[AsAlias] para asignar un alias de RemoteInterface aButtonRemote, de modo que cuando tecleamos RemoteInterface, nos da el servicioButtonRemote. Pero, ¡esto rompió nuestro registro! Tenemos que decirle a Symfony que nos dé LoggerRemote en su lugar, pero que pase el servicio ButtonRemote aLoggerRemote.

#[AsDecorator]

Básicamente, tenemos que decirle a Symfony que ButtonRemote está siendo decorado por LoggerRemote. Para ello, en LoggerRemote, utiliza otro atributo: #[AsDecorator] pasando el servicio que decora: ButtonRemote::class:

38 lines | src/Remote/LoggerRemote.php
// ... lines 1 - 5
use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
// ... line 7
#[AsDecorator(ButtonRemote::class)]
final class LoggerRemote implements RemoteInterface
// ... lines 10 - 38

Esto le dice a Symfony:

Oye, si algo te pide el servicio ButtonRemote, dale LoggerRemote en su lugar.

En esencia, Symfony intercambia los servicios y convierte ButtonRemote en el servicio "interno" de LoggerRemote. Esto solidifica la necesidad del RemoteInterface que creamos antes. Si intentáramos inyectar directamente ButtonRemote, obtendríamos un error de tipo porque Symfony estaría intentando inyectar LoggerRemote.

Decoración del servicio

Así que, sígueme en esto: autoconectamos RemoteInterface. Eso está aliasado a ButtonRemote, así que Symfony intenta darnos eso. Pero entonces, gracias a #[AsDecorator], lo cambia por LoggerRemote... pero pasa ButtonRemote a LoggerRemote. En resumen, AsDecorator nos permite decorar un servicio existente con otro.

Vuelve a la aplicación, actualízala y... pulsa "subir volumen". Comprueba el panel del perfilador "Registros" y... ¡estamos registrando de nuevo!

Decoradores múltiples

Utilizar #[AsDecorator] hace que sea superfácil añadir múltiples decoradores. Quizá queramos añadir un decorador de limitación de velocidad para evitar que los niños machaquen botones. Sólo tendríamos que crear una clase RateLimitingRemote que implemente RemoteInterface y añadir#[AsDecorator(ButtonRemote::class)].

#[AsDecorator(ButtonRemote::class)]
class RateLimitingRemote implements RemoteInterface
{
    public function __construct(
        private RateLimiter $rateLimiter,
        private RemoteInterface $inner,
    ) {
    }

    // ...
}

A continuación: Añadiremos un canal de registro personalizado y exploraremos el "autocableado con nombre"