9: Instantiebeheer

Phlo gebruikt zijn eigen instance manager om objecten efficiënt en voorspelbaar te initialiseren en opnieuw te gebruiken. Dit systeem bepaalt wanneer controller code wordt uitgevoerd, hoe instanties worden opgeslagen en hoe circulaire referenties worden voorkomen.

9.1: De basisprincipes

Wanneer je een .phlo-bestand definieert, verandert de build-fase het in een klasse. Elke aanroep naar een object via %name gaat via de instance manager (phlo() in /phlo/phlo.php).

Voorbeeld:

prop title = 'Welkom'

route GET home => $this->main

method main => view($this->home)

view home:
<h1>$this->title</h1>

Wanneer de route /home wordt aangevraagd:

  1. De instance manager controleert of er al een instantie van deze klasse bestaat.
  2. Zo niet, dan wordt deze gemaakt en opgeslagen.
  3. Na creatie wordt de controllercode uitgevoerd (zie §8.2).
  4. Vervolgens wordt de aangevraagde methode aangeroepen.

9.2: Controller code

Alle code in een .phlo-bestand die niet behoort tot route, prop, static, method, function, view, <style> of <script> is controller code. Deze code wordt uitgevoerd na de instantie zodra de instantie volledig bestaat.

Voorbeeld:

prop ready = false

%session->start()
$this->ready = true

De laatste twee regels zijn controller code omdat ze op het hoogste niveau staan.

9.3: De rol van `__handle()`

Phlo genereert een speciale __handle() methode voor elke klasse. De instantiebeheerder roept deze aan wanneer een instantie wordt opgevraagd via %name.

__handle():

Je roept __handle() nooit zelf aan of overschrijft deze; het is onderdeel van de gegenereerde klasse en de instantiebeheerder.

9.4: Luie initialisatie

Omdat controllercode alleen na constructie wordt uitgevoerd, kunnen instanties elkaar verwijzen zonder ongewenste recursieve creatie te activeren.

Voorbeeld:

a.phlo:

prop message = 'A ready'

b.phlo:

prop message = 'B ready'

main.phlo:

route GET test => $this->show

method show {
  dx(%a->message, %b->message)
}

9.5: De obj basis klasse: powertools

Elke gecompileerde klasse breidt obj uit, en obj is meer dan __get/__set. Dit zijn de tools die je gebruikt wanneer een klasse dynamisch moet functioneren.

Interceptie haakjes. Implementeer objCall, objGet of objSet om de toegangsketen te vangen. Het retourneren van null valt terug op het normale gedrag; alles wat niet-null is, kortsluit:

method objGet($key) => $this->cache[$key] ?? null

method objCall($method, ...$args) => str_starts_with($method, 'find') ? $this->finder($method, $args) : null

method objSet($key, $value) => $key === 'id' ? true : null

objGet wordt uitgevoerd voordat data/closure/methode/prop lookup plaatsvindt bij elke lezing, objCall bij elke onbekende methode-aanroep, en objSet voordat elke schrijfoperatie plaatsvindt (een niet-null retour onderdrukt de schrijfoperatie). Dit is het mechanisme achter decorators, lazy loading en read-only guards.

Gebonden closures. Wijs een closure toe en deze bindt zich aan de instantie: $obj->greet = fn() => "Hi $this->name", later draait $obj->greet() met $this gebonden. Handig voor per-instantie gedrag zonder subclassing.

Data API. objImport(name: 'x', age: 3) wijst in bulk toe en retourneert $this (ketenbaar). objKeys(), objValues() en objLength() inspecteren de data; objClear() wist het. Itereren over een obj (foreach $record AS $key => $value) en json_encode($record) onthullen precies de opgeslagen data. Elke schrijfoperatie schakelt objChanged in, de dirty flag die de ORM gebruikt om te beslissen of objSave iets schrijft.

Gecachede computed props. prop x => ... cachet bij de eerste toegang; de argumentvorm cachet per argumentenset. Hetzelfde geldt voor computed statics, gecached per klasse.

Worker persistentie. prop objPers = true zorgt ervoor dat een instantie overleeft tussen requests in worker-modus: het phlo() register houdt alleen objPers instanties vast bij zijn reset per request. Geschikt voor DB-verbindingen en geparsed configuraties; ongeschikt voor alles wat request- of gebruikersgebonden is.

Les. Een gewone prop in een bovenliggende klasse SCHADUWT een computed prop in een kind. prop dir = void in een abstracte bovenliggende klasse compileert naar een echte PHP-eigenschap, zodat de getter van een kind prop dir => guide nooit wordt geraadpleegd: $this->dir leest stilletjes void. Wanneer kinderen moeten overschrijven met een computed prop, verklaar de bovenliggende prop ook als computed: prop dir => void.

9.6: Best practices

We gebruiken essentiële cookies om deze site te laten werken. Met uw toestemming gebruiken we ook analytics om de site te verbeteren.