Modelo de componentes
Un concepto importante en Nette es el componente. Insertamos componentes interactivos visuales en las páginas, los formularios
o todos sus elementos también son componentes. Las dos clases base de las que heredan todos estos componentes forman parte del
paquete nette/component-model
y su propósito es crear una jerarquía de componentes en forma de árbol.
Component
Nette\ComponentModel\Component
es el ancestro común de todos los componentes. Contiene los métodos getName()
que devuelven el nombre del
componente y el método getParent()
que devuelve su padre. Ambos se pueden establecer con el método
setParent()
: el primer parámetro es el padre y el segundo es el nombre del componente.
lookup (string $type): ?Component
Busca un objeto de la clase o interfaz requerida hacia arriba en la jerarquía. Por ejemplo,
$component->lookup(Nette\Application\UI\Presenter::class)
devuelve el presenter si el componente está adjunto a
él, incluso a través de varios niveles.
lookupPath (string $type): ?string
Devuelve la llamada ruta, que es una cadena creada concatenando los nombres de todos los componentes en la ruta entre el
componente actual y el buscado. Así, por ejemplo, $component->lookupPath(Nette\Application\UI\Presenter::class)
devuelve un identificador único del componente en relación con el presenter.
Container
Nette\ComponentModel\Container
es el componente padre, es decir, un componente que contiene hijos y, por lo tanto, forma una estructura de árbol. Dispone de
métodos para agregar, obtener y eliminar objetos fácilmente. Es el ancestro, por ejemplo, del formulario o de las clases
Control
y Presenter
.
getComponent (string $name): ?Component
Devuelve un componente. Al intentar obtener un hijo indefinido, se llama a la fábrica createComponent($name)
. El
método createComponent($name)
llama al método createComponent<nombre del componente>
en el
componente actual y le pasa el nombre del componente como parámetro. El componente creado se agrega luego al componente actual
como su hijo. Llamamos a estos métodos fábricas de componentes y pueden ser implementados por descendientes de la clase
Container
.
getComponents(): array
Devuelve los hijos directos como un array. Las claves contienen los nombres de estos componentes. Nota: en la versión 3.0.x, el método devolvía un iterador en lugar de un array, y su primer parámetro determinaba si los componentes debían recorrerse en profundidad, y el segundo representaba un filtro de tipo. Estos parámetros están obsoletos.
getComponentTree(): array
Obtiene toda la jerarquía de componentes, incluidos todos los subcomponentes anidados, como un array indexado. La búsqueda va primero en profundidad.
Monitorización de ancestros
El modelo de componentes de Nette permite un trabajo muy dinámico con el árbol (podemos eliminar, mover, agregar componentes), por lo que sería un error confiar en que después de crear un componente, el padre, el padre del padre, etc., se conozcan inmediatamente (en el constructor). En la mayoría de los casos, el padre no se conoce en absoluto en el momento de la creación.
¿Cómo saber cuándo se adjuntó un componente al árbol del presenter? Observar el cambio del padre no es suficiente, porque
el padre del padre podría haber sido adjuntado al presenter, por ejemplo. El método monitor($type, $attached,
$detached) ayuda. Cada componente puede monitorizar cualquier número de clases e interfaces. El adjunto o desadjunto se
anuncia llamando al callback $attached
o $detached
, respectivamente, y pasando el objeto de la clase
monitorizada.
Para una mejor comprensión, un ejemplo: la clase UploadControl
, que representa el elemento de formulario para la
carga de archivos en Nette Forms, debe establecer el atributo enctype
del formulario en el valor
multipart/form-data
. Sin embargo, en el momento de la creación del objeto, es posible que no esté adjunto a ningún
formulario. ¿En qué momento, entonces, modificar el formulario? La solución es simple: en el constructor, solicite la
monitorización:
class UploadControl extends Nette\Forms\Controls\BaseControl
{
public function __construct($label)
{
$this->monitor(Nette\Forms\Form::class, function ($form): void {
$form->setHtmlAttribute('enctype', 'multipart/form-data');
});
// ...
}
// ...
}
y tan pronto como el formulario esté disponible, se llama al callback. (Anteriormente, se usaba el método común
attached
o detached
en su lugar).