Métodos y atributos inject
En este artículo, nos centraremos en las diferentes formas de pasar dependencias a los Presenters en el
framework Nette. Compararemos la forma preferida, que es el constructor, con otras opciones como los métodos y atributos
inject
.
También para los Presenters, pasar dependencias mediante el constructor es la ruta
preferida. Sin embargo, si creas un ancestro común del que heredan otros Presenters (p. ej., BasePresenter
), y este
ancestro también tiene dependencias, surge un problema que llamamos constructor hell. Esto se puede
evitar utilizando rutas alternativas, que son los métodos y atributos (anotaciones) inject
.
Métodos inject*()
Es una forma de pasar dependencias mediante setter. El nombre de estos
setters comienza con el prefijo inject
. Nette DI llama automáticamente a los métodos con este nombre justo después
de crear la instancia del Presenter y les pasa todas las dependencias requeridas. Por lo tanto, deben declararse como public.
Los métodos inject*()
pueden considerarse como una especie de extensión del constructor en múltiples métodos.
Gracias a esto, BasePresenter
puede recibir dependencias a través de otro método y dejar el constructor libre para
sus descendientes:
abstract class BasePresenter extends Nette\Application\UI\Presenter
{
private Foo $foo;
public function injectBase(Foo $foo): void
{
$this->foo = $foo;
}
}
class MyPresenter extends BasePresenter
{
private Bar $bar;
public function __construct(Bar $bar)
{
$this->bar = $bar;
}
}
Un Presenter puede contener cualquier número de métodos inject*()
y cada uno puede tener cualquier número de
parámetros. También son excelentes en casos donde el Presenter está compuesto de traits y cada uno requiere su propia
dependencia.
Atributos Inject
Es una forma de inyección en la propiedad. Simplemente marca en qué variables se debe inyectar, y Nette DI pasa automáticamente las dependencias justo después de crear la instancia del Presenter. Para poder insertarlas, es necesario declararlas como public.
Marcamos las propiedades con un atributo: (anteriormente se usaba la anotación /** @inject */
)
use Nette\DI\Attributes\Inject; // esta línea es importante
class MyPresenter extends Nette\Application\UI\Presenter
{
#[Inject]
public Cache $cache;
}
La ventaja de esta forma de pasar dependencias era una sintaxis muy concisa. Sin embargo, con la llegada de constructor property promotion, parece más fácil usar el constructor.
Por el contrario, esta forma sufre las mismas deficiencias que pasar dependencias a propiedades en general: no tenemos control sobre los cambios en la variable y, al mismo tiempo, la variable se convierte en parte de la interfaz pública de la clase, lo cual no es deseable.