Komponenten-Modell

Ein wichtiges Konzept in Nette ist die Komponente. Wir fügen visuelle interaktive Komponenten in Seiten, Formulare oder alle ihre Elemente sind ebenfalls Komponenten. Es gibt zwei Basisklassen, von denen alle diese Komponenten erben, die Teil des Pakets nette/component-model sind und für die Erstellung der Komponentenbaumhierarchie verantwortlich sind.

Component

Nette\ComponentModel\Component ist der gemeinsame Vorfahre aller Komponenten. Sie enthält die Methode getName(), die den Namen der Komponente zurückgibt, und die Methode getParent(), die die übergeordnete Komponente zurückgibt. Beide können mit der Methode setParent() gesetzt werden – der erste Parameter ist der Elternteil und der zweite der Komponentenname.

lookup(string $type): ?Component

Sucht in der Hierarchie nach einem Objekt der gewünschten Klasse oder Schnittstelle. Zum Beispiel gibt $component->lookup(Nette\Application\UI\Presenter::class) presenter zurück, wenn die Komponente trotz mehrerer Ebenen mit ihm verbunden ist.

lookupPath(string $type): ?string

Gibt den so genannten Pfad zurück, d. h. eine Zeichenkette, die aus der Verkettung der Namen aller Komponenten auf dem Pfad zwischen der aktuellen Komponente und der gesuchten Komponente besteht. So gibt z. B. $component->lookupPath(Nette\Application\UI\Presenter::class) den eindeutigen Bezeichner der Komponente relativ zum Präsentator zurück.

Container

Nette\ComponentModel\Container ist die übergeordnete Komponente, d. h. die Komponente, die die Kinder enthält und somit die Baumstruktur bildet. Er verfügt über Methoden zum einfachen Hinzufügen, Abrufen und Entfernen von Komponenten. Er ist der Vorfahre z.B. des Formulars oder der Klassen Control und Presenter.

getComponent(string $name): ?Component

Gibt eine Komponente zurück. Der Versuch, ein undefiniertes Kind aufzurufen, führt zum Aufruf der Fabrik createComponent($name). Die Methode createComponent($name) ruft die Methode createComponent<component name> in der aktuellen Komponente auf und übergibt den Namen der Komponente als Parameter. Die erstellte Komponente wird dann an die aktuelle Komponente als ihr Kind übergeben. Wir nennen diese Komponentenfabriken, sie können in von Container geerbten Klassen implementiert werden.

getComponents(): array

Gibt direkte Nachkommen als Array zurück. Die Schlüssel enthalten die Namen dieser Komponenten. Hinweis: In Version 3.0.x gab die Methode einen Iterator statt eines Arrays zurück. Der erste Parameter gab an, ob durch die Komponenten in der Tiefe iteriert werden sollte, und der zweite Parameter stellte einen Typfilter dar. Diese Parameter sind veraltet.

getComponentTree(): array

Gibt die gesamte Hierarchie der Komponenten, einschließlich aller verschachtelten untergeordneten Komponenten, als indiziertes Array zurück. Die Suche geht zunächst in die Tiefe.

Überwachung der Vorfahren

Das Nette-Komponentenmodell erlaubt eine sehr dynamische Baumarbeit (wir können Komponenten entfernen, verschieben, hinzufügen), so dass es ein Fehler wäre, sich darauf zu verlassen, dass nach dem Erstellen einer Komponente der Elternteil, der Elternteil des Elternteils usw. sofort bekannt sind (im Konstruktor). Normalerweise ist das Elternteil bei der Erstellung der Komponente überhaupt nicht bekannt.

Wie kann man herausfinden, wann eine Komponente zum Präsentationsbaum hinzugefügt wurde? Es reicht nicht aus, die Änderung des Parents zu verfolgen, denn der Parent des Parents könnte z.B. an den Presenter angehängt worden sein. Die monitor($type, $attached, $detached) Methode kann hier helfen. Jede Komponente kann eine beliebige Anzahl von Klassen und Schnittstellen überwachen. Die Verbindung oder Trennung wird durch den Aufruf der Callbacks $attached bzw. $detached angekündigt, wobei das Objekt der überwachten Klasse übergeben wird.

Ein Beispiel: Die Klasse UploadControl, die das Formularelement zum Hochladen von Dateien in Nette Forms repräsentiert, muss das Attribut enctype des Formulars auf den Wert multipart/form-data setzen. Zum Zeitpunkt der Erstellung des Objekts muss es jedoch an kein Formular angehängt sein. Wann soll das Formular geändert werden? Die Lösung ist einfach – wir erstellen eine Anfrage zur Überwachung im Konstruktor:

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');
		});
		// ...
	}

	// ...
}

und wenn das Formular verfügbar ist, wird der Callback aufgerufen. (Zuvor wurden stattdessen die üblichen Methoden attached und detached verwendet).

Version: 3.x