Decorar un servicio con AsDecorator
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.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeEn 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
:
// ... lines 1 - 5 | |
use Symfony\Component\DependencyInjection\Attribute\AsDecorator; | |
// ... line 7 | |
ButtonRemote::class) | (|
final class LoggerRemote implements RemoteInterface | |
// ... lines 10 - 38 |
Esto le dice a Symfony:
Oye, si algo te pide el servicio
ButtonRemote
, daleLoggerRemote
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"