3: Runtime-config
data/app.json beschrijft de build, wat gecompileerd wordt. Dit hoofdstuk behandelt de runtime, wat er gebeurt bij elke aanvraag. Die configuratie bevindt zich in www/app.php (en, voor stage/release, release/www/app.php) als argumenten voor phlo_app(...).
<?php
require('/srv/phlo/phlo.php');
phlo_app (
id: 'Example',
host: 'dev.example.nl',
auth: true,
build: true,
debug: true,
app: '/srv/example.nl/',
)
Elke sleutel is een genaamde parameter die ook een PHP constante wordt, overal in je app beschikbaar als een enkel woord (host, data, composer, enz.). Hetzelfde geldt voor je eigen aangepaste sleutels.
3.1: Identiteit en host
| Sleutel | Standaard | Doel |
|---|---|---|
id |
geen | Vrije naam voor de app, gebruikt door het Phlo Control Center, het Phlo Dashboard en logs |
host |
null |
Vhost waarop dit toegangspunt is toegestaan om te draaien. Phlo weigert verzoeken die niet overeenkomen, geen onbedoelde cross-host reacties |
3.2: Modi: `build`, `debug`, `auth`, `thread`
| Sleutel | Standaard | Effect |
|---|---|---|
build |
false |
Schakelt de build/lint/reflect CLI in en laat Phlo gewijzigde bronnen per verzoek detecteren en opnieuw compileren |
debug |
false |
Laadt debug.php, activeert debug() / dx() / debug helpers, geeft volledige stacktraces in plaats van generieke 500-fouten |
auth |
false |
Site-brede HTTP Basic-authenticatie met inloggegevens in data/auth.ini |
thread |
false |
Worker-modus (zie X.7), true = onbeperkt, geheel getal = aantal verzoeken per worker |
Combineer niet: build: true en thread: true. Build schrijft bestanden tussen verzoeken; in een langdurige worker is dat onveilig. Phlo gooit een runtime-fout als beide aan staan.
Vereist: auth: true heeft build: true nodig. Phlo geeft een foutmelding bij het opstarten als auth is ingesteld zonder build. (Dit is een implementatiedetail: de site-brede auth-handler wordt in de build-laag geleverd. Om een host zonder build-fase te beschermen, plaats je HTTP Basic-authenticatie in je webserver voor Phlo.)
Control Center-pad: wanneer build: true en debug: true, wordt het Phlo Control Center automatisch gemonteerd op /phlo, geen configuratie nodig. Gebruik de optionele control: sleutel om het op een ander pad te monteren (control: 'admin' serveert het op /admin) of stel control: false in om het uit te schakelen. De oudere dashboard: sleutel deed hetzelfde en werkt voorlopig nog steeds, maar control: is de huidige naam. Buiten build+debug is het ongeacht uitgeschakeld.
3.3: Paden
Alleen app is vereist. De rest valt terug op subdirectories van app:
| Sleutel | Standaard | Bedoeld voor |
|---|---|---|
app |
(vereist) | App root |
data |
<app>/data/ |
Config (app.json, auth.ini), referenties, runtime status |
php |
<app>/php/ |
Gegenereerde PHP, wijzig dit alleen wanneer de release-uitvoer elders is opgeslagen |
www |
<app>/www/ |
Web root |
Je release entrypoint stelt doorgaans app: '<app>/release/' en php: '<app>/release/' in, zodat de release-uitvoer wordt geserveerd zonder buildmodus.
3.4: Control Center en WebSocket
| Sleutel | Standaard | Effect |
|---|---|---|
control |
'phlo' met build+debug, anders false |
URL-prefix waaronder de control UI zich bevindt. Bijvoorbeeld 'beheer' → /beheer; false = uit |
websocket |
null |
Poort waarop phloWS draait voor deze app. Wordt de constante websocket, gebruikt door wsCast() |
De control UI vereist build: true. Zie het hoofdstuk over WebSocket voor de phloWS-configuratie.
3.5: Composer autoload
Wil je PHP-pakketten gebruiken vanuit vendor/? Geef het pad op:
phlo_app (
composer: '/srv/example.nl/',
...
)
Phlo registreert dan een lazy autoloader die alleen <composer>/vendor/autoload.php laadt wanneer een onbekende klasse moet worden opgelost. Geen cold-start kosten als je nooit Composer-pakketten aanraakt; volledige Composer autoload zodra je dat doet.
Conventie: composer: '<app>/data/' (de composer.json en vendor/ bevinden zich dan in data/, buiten de webroot).
3.6: Trace en CLI
| Sleutel | Standaard | Effect |
|---|---|---|
trace |
false |
Schakelt de trace-modus in, zie het Trace-hoofdstuk |
cli |
'php-zts' (indien ZTS) of 'php' |
Pad naar de PHP-binaire die Phlo gebruikt voor subprocessen (build, taken, websocket). Overschrijf dit als je systeem niet-standaard PHP-binaries heeft |
cliis een string in v4 (een pad), niet een boolean zoals in v1.
3.7: Werknormregels
thread: true zet Phlo in de modus voor langdurige worker (FrankenPHP, ReactPHP, RoadRunner). De runtime blijft in het geheugen tussen verzoeken. Drie regels die je moet weten:
1. Geen die() of exit() in het HTTP-pad. Beide beëindigen de hele worker. Gebruik return of laat een beëindigende oproep (view(), apply(), location()) de respons verzenden.
2. Geen verzoekstatus in statische eigenschappen. Statics overleven tussen verzoeken in een worker; gebruikersgegevens van verzoek A lekken naar verzoek B. Voor caches die worker-veilig zijn (klasstructuur, berekende metadata), zijn statics prima, niet voor sessie-, gebruikers-, payload-, tijd- of DB-status.
3. Markeer langdurige objecten met $objPers = true. Standaard wist Phlo zijn instantiekaart tussen verzoeken. Voor objecten die je expliciet wilt hergebruiken (DB-verbinding, voorbereide statements), stel $this->objPers = true in zodat de opruiming ze met rust laat.
3.8: Aangepaste sleutels: je eigen constanten
Elke extra benoemde parameter die je doorgeeft aan phlo_app() wordt automatisch een PHP-constante. Dit is de manier om app-brede paden of functie-vlaggen te declareren:
phlo_app (
app: '/srv/example.nl/',
langs: '/srv/example.nl/langs/',
files: '/srv/example.nl/files/',
uploads: '/srv/example.nl/data/uploads/',
)
Direct bruikbaar in .phlo daarna:
$dict = parse_ini_file(langs.'en.ini')
$path = files.'avatars/'.$user->id.'.jpg'
$url = uploads
reflect::runtime toont alle gedefinieerde constanten. Handig om te ontdekken wat een app biedt zonder www/app.php te openen.
3.9: Voorbeeld: dev en release naast elkaar
phlo_app (
id: 'Example',
host: 'dev.example.nl',
auth: true,
build: true,
debug: true,
trace: true,
app: '/srv/example.nl/',
composer: '/srv/example.nl/data/',
websocket: 3001,
langs: '/srv/example.nl/langs/',
)
phlo_app (
id: 'Example',
host: 'example.nl',
thread: true,
app: '/srv/example.nl/release/',
php: '/srv/example.nl/release/',
data: '/srv/example.nl/data/',
composer: '/srv/example.nl/data/',
websocket: 3001,
langs: '/srv/example.nl/langs/',
)
Dev heeft build, debug, auth, het Control Center en trace. Release heeft worker mode (thread) en wijst de webroot/php-uitvoer naar release/. data, composer, langs blijven hetzelfde, dat is gedeelde staat.
3.10: De request en response objecten
Twee runtime-objecten dragen elke aanvraag. %req (lezen) en %res (schrijven) zijn altijd beschikbaar.
%req berekende eigenschappen:
| Eigenschap | Bevat |
|---|---|
%req->method |
HTTP-werkwoord, in hoofdletters |
%req->path |
Aanvraagpad zonder leidende schuine streep |
%req->part($i) |
Padsegment op index |
%req->query |
Geparsed querystring-array |
%req->async |
true wanneer de aanvraag afkomstig is van phlo.js (SPA-navigatie, asynchrone formulieren) |
%req->cli |
true wanneer uitgevoerd vanaf de opdrachtregel |
%req->secure, %req->scheme, %req->base, %req->url |
URL-onderdelen, eenmaal berekend |
%req->referer, %req->acceptLanguage |
Veelvoorkomende headers, genormaliseerd |
%res oppervlak:
| Lid | Doet |
|---|---|
%res->header($key, $value) |
Plaatst een responsheader in de wachtrij (verzonden bij renderen) |
%res->type |
Content-Type voor de respons |
%res->text($body) / %res->json(...) / %res->xml($body) |
Stelt de body in (en type voor json/xml); ketenbaar |
%res->render($code = null) |
Verzendt status, headers en body; markeert de respons als voltooid |
%res->streaming |
true schakelt apply() over naar onmiddellijke flush-per-opdracht (zie het WebSocket-hoofdstuk) |
%res->status, %res->done |
Statuscode; of de output al is verzonden |
output($content, $filename = null, $attachment = null, $file = null, $code = null, $type = null) is de responsfunctie voor bestanden, blobs en JSON-met-een-status: het dient een bestand (mime op naam, optionele attachment), of JSON wanneer $content een array is (output(['id' => $id], code: 201), output(['error' => 'not found'], code: 404)); type overschrijft de content-type voor een vooraf-gecodeerde string body. view()/apply()/output()/error()/location() zijn de responsfuncties die app-code gebruikt; de %res->json/text/xml/render leden hierboven zijn de low-level primitieve waar ze op bouwen, voor de zeldzame hand-geassembleerde respons (aangepaste headers, een speciale content-type). Verpak ze niet in per-app jsonOut()/respond() helpers.
Les.
die($content)lijkt alsof het "een respons verzendt", maar het omzeiltrender(): geplaatste headers (inclusief Content-Type) verlaten nooit de server, en in worker-modus beëindigtdie()de hele worker. Deze site diende zijn machine-leesbare eindpunten wekenlang alstext/htmlop die manier. Eindig altijd metoutput(...),view(),apply(),location()of een expliciete%res->...->render().
Runtime-fouten landen in data/errors.json met bericht, source-mapped .phlo bestand en regel, de host, een teller en de laatste gebeurtenis (gededupliceerd per host + locatie + bericht). Lees ze met reflect::errors [limit] of in het Phlo Control Center.