Métodos y atributos inject
Este artículo se centra en las distintas formas de pasar dependencias a los presenters dentro del framework
Nette. Compararemos el método preferido, la inyección por constructor, con alternativas como los métodos y atributos
inject.
Para los presenters, igual que para las demás clases, el enfoque preferido es pasar las dependencias por el constructor. Ahora
bien, si crea un antecesor común del que heredan los demás presenters (p. ej. BasePresenter) y ese antecesor
también necesita dependencias, puede surgir el problema conocido como infierno del
constructor. Se puede sortear con métodos alternativos, en concreto con los métodos y atributos inject (antes
anotaciones).
Métodos inject*()
Es una forma de pasar dependencias mediante setters. Los nombres de
estos setters deben empezar con el prefijo inject. Nette DI llama automáticamente a los métodos así llamados justo
después de crear la instancia del presenter y les pasa todas las dependencias necesarias. Por eso deben declararse públicos.
Los métodos inject*() se pueden ver como una ampliación del constructor repartida en varios métodos. Eso
permite que BasePresenter reciba sus dependencias mediante un método aparte y deje 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 tener cualquier número de métodos inject*() y cada uno puede aceptar cualquier número de
parámetros. Este enfoque encaja bien también cuando un presenter está compuesto por traits y cada trait necesita sus propias
dependencias.
Atributos Inject
Es una forma de inyectar en propiedades. Basta con marcar las propiedades que deben inyectarse y Nette DI pasará automáticamente las dependencias justo después de crear la instancia del presenter. Para permitir la inyección, estas propiedades deben declararse públicas.
Las propiedades se marcan con un atributo: (antes 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 su sintaxis muy concisa. Pero con la llegada de la promoción de propiedades en el constructor, usar el constructor suele parecer más sencillo.
Por el contrario, este método adolece de los mismos inconvenientes que la inyección en propiedades en general: perdemos el control sobre los cambios de la variable y la variable pasa a formar parte de la interfaz pública de la clase, lo cual no suele ser deseable.