Komponens modell
A Nette egyik fontos fogalma a komponens. Vizuális
interaktív komponenseket illesztünk be az oldalakba, űrlapokba, illetve azok minden eleme is komponens. Két alaposztály
van, amelyektől az összes ilyen komponens öröklődik, a nette/component-model
csomag részét képezik, és a
komponensfa hierarchiájának létrehozásáért felelősek.
Component
Nette\ComponentModel\Component
az összes komponens közös őse. Tartalmazza a getName()
metódust, amely a komponens nevét adja vissza, és a
getParent()
metódust, amely a szülőjét adja vissza. Mindkettő a setParent()
metódussal
állítható be – az első paraméter a szülő, a második pedig a komponens neve.
lookup (string $type): ?Component
A hierarchiában felfelé keres egy objektumot a kívánt osztályból vagy interfészből. Például a
$component->lookup(Nette\Application\UI\Presenter::class)
visszaadja a presenter-t, ha a komponens több szint
ellenére is kapcsolódik hozzá.
lookupPath (string $type): ?string
Visszaadja az úgynevezett útvonalat, amely az aktuális komponens és a keresett komponens közötti útvonalon lévő
összes komponens nevének összekapcsolásával képzett karakterlánc. Így például a
$component->lookupPath(Nette\Application\UI\Presenter::class)
a komponens egyedi azonosítóját adja vissza a
bemutatóhoz képest.
Container
Nette\ComponentModel\Container a
szülő komponens, azaz az a komponens, amely a gyermekeket tartalmazza, és így a fa szerkezetét alkotja. Módszerekkel
rendelkezik a komponensek egyszerű hozzáadásához, visszakereséséhez és eltávolításához. Őse például az űrlapnak
vagy a Control
és a Presenter
osztályoknak.
getComponent (string $name): ?Component
Visszaad egy komponenst. A nem definiált gyermek hívásának kísérlete a factory createComponent($name)
meghívását okozza. A createComponent($name)
metódus meghívja a metódust
createComponent<component name>
az aktuális komponensben, és paraméterként átadja a komponens nevét.
A létrehozott komponens ezután átadásra kerül az aktuális komponensnek, mint annak gyermeke. Ezeket a komponens gyáraknak
nevezzük, a Container
-tól örökölt osztályokban implementálhatók.
getComponents(): array
Közvetlen leszármazottakat ad vissza tömbként. A kulcsok ezen komponensek nevét tartalmazzák. Megjegyzés: a 3.0.x verzióban a módszer tömb helyett egy iterátort adott vissza, és az első paramétere megadta, hogy a komponenseket mélységben iterálja-e, a második pedig egy típusszűrőt jelentett. Ezek a paraméterek elavultak.
getComponentTree(): array
Visszaadja a komponensek teljes hierarchiáját, beleértve az összes beágyazott gyermekkomponenst indexelt tömbként. A keresés először a mélységben történik.
Az ősök figyelése
A Nette komponensmodell nagyon dinamikus famunkát tesz lehetővé (komponenseket távolíthatunk el, mozgathatunk, adhatunk hozzá), ezért hiba lenne arra hagyatkozni, hogy egy komponens létrehozása után azonnal (a konstruktorban) ismert a szülő, a szülő szülője, stb. Általában a szülő egyáltalán nem ismert a komponens létrehozásakor.
Hogyan lehet megtudni, hogy egy komponens mikor került hozzá a prezenterfához? A szülő változásának nyomon követése
nem elegendő, mert a szülő szülője például a prezenterhez csatolódhatott. A monitor($type, $attached,
$detached) metódus segíthet. Minden komponens tetszőleges számú osztályt és interfészt monitorozhat. A csatlakozást
vagy szétkapcsolódást a $attached
illetve a $detached
visszahívások meghívásával és a
megfigyelt osztály objektumának átadásával jelentjük be.
Egy példa: A UploadControl
osztály, amely a Nette Forms-ben a fájlok feltöltésére szolgáló űrlapelemet
képviseli, az űrlap enctype
attribútumát a multipart/form-data
értékre kell állítani. Az
objektum létrehozásakor azonban nem kell semmilyen űrlaphoz csatolni. Mikor kell módosítani az űrlapot? A megoldás
egyszerű – a konstruktorban létrehozunk egy megfigyelési kérelmet:
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');
});
// ...
}
// ...
}
és amikor az űrlap elérhetővé válik, a visszahívást hívjuk meg. (Korábban a attached
és a
detached
közös metódusokat használtuk helyette.)