21: Filosofie
Dit hoofdstuk legt uit waarom Phlo is gebouwd zoals het is: de weloverwogen afwegingen achter de parser, de transpiler, de runtime en de tooling. De korte versie: Phlo is een geïntegreerd platform met zijn eigen full-stack taal, en de kracht ligt in de verticale integratie van alle lagen, één taal en één mentaal model van code tot fleet.
Onder elke afweging ligt één intentie: een persoon of een klein team weer eigenaarschap en toezicht te geven over wat ze bouwen. Veel moderne webontwikkeling werkt stilletjes tegen dat doel. Afhankelijkheidsbomen die te diep zijn om te auditen, frameworks die sneller veranderen dan je ze kunt leren, ceremonie en boilerplate die verbergen wat de code daadwerkelijk doet, en gebruiksgebaseerde hosting waarvan de rekening precies groeit wanneer je succesvol bent. Elk van deze voegt een laag toe tussen jou en je software, totdat geen enkele persoon het hele plaatje meer in handen heeft en de kosten van het draaien ervan niet langer door jou te voorspellen zijn. Phlo beschouwt deze als paradigma's om van weg te stappen, niet om aan te nemen. Code bevat geen decoratie die niet nodig is, zodat het leesbaar en reviewbaar blijft in één zitting. De output is eenvoudige PHP die jij bezit. Het draait op een machine die jij controleert, tegen een kost die de machine volgt in plaats van elke aanvraag. Leesbaarheid, eigenaarschap en betaalbaarheid zijn geen functies die bovenop zijn toegevoegd; ze zijn het doel, en de secties hieronder zijn hoe de taal ze verdient.
21.1: Eén systeem, vier lagen
Phlo is geen bibliotheek die je aan een stack toevoegt; het is de stack. Vier lagen delen één ontwerp:
- De taal: aangepaste
.phlosyntaxis die transpileert naar leesbare PHP, CSS en JavaScript. - Het applicatieplatform: de backend (
obj, resources, functies) en de frontend (phlo.js, de geïntegreerde SPA-engine, hetapply()protocol) spreken hetzelfde protocol, zodat een route de pagina kan bijwerken zonder dat je client glue hoeft te schrijven. - Het serverplatform: de Phlo Daemon en Phlo Realtime voor realtime, Phlo WhatsApp als WhatsApp-gateway, mail, en FrankenPHP worker-modus voor productie.
- Het operationsplatform: het Phlo Dashboard (een aparte applicatie) beheert je fleet, hosts, domeinen, databases en meldingen.
Elke laag zou op zichzelf onopvallend zijn. Samen betekent dit dat je nooit tussen ecosystemen hoeft te vertalen: dezelfde conventies, dezelfde foutpagina's, dezelfde CLI, van een enkele view naar een fleet van servers. Een vergelijking zoals "een compacte alternatieve voor Laravel of HTMX" raakt slechts één laag en mist het punt.
21.2: Een regelgebaseerde parser, geen AST
Phlo leest de bronregel voor regel: een verklaring eindigt bij een regelafbreking, een node-header opent een blok, een lege regel sluit een view. Er is geen tokenizer die een abstracte syntaxisboom opbouwt. De hele parser is een paar honderd regels, leesbaar in één zitting, en omdat regel N overeenkomt met een bekende regel uit, komen de sourcemap en de foutpagina's bijna gratis.
Het model voor regelafbrekingen is compleet en klein: elke regel krijgt een ;, regels die eindigen op ( [ { } , of . zijn impliciete voortzettingen, en een afsluitende \ gaat expliciet verder (zie hoofdstuk 4).
De kosten zijn strengheid: geen meerregelige geciteerde strings, een lege regel beëindigt een view, CSS-declaraties blijven op één regel. Phlo's antwoord is betere diagnostiek, niet een vergevingsgezinde parser: overtredingen stoppen de build met het .phlo-bestand en de regel. Een echte grammatica zou de regels versoepelen ten koste van de leesbaarheid van de parser, en dat is geen ruil die Phlo maakt.
21.3: Transpileert naar leesbaar PHP
.phlo transpileert naar gewone PHP-klassen: één klasse per bestand, een header die de bron benoemt, en een per-klasse sourcemap die de PHP-regel naar de .phlo-regel vastlegt. Je kunt altijd in de gegenereerde PHP duiken om precies te zien wat er draait; er is geen verborgen runtime die sjablonen interpreteert. En wanneer er iets misgaat tijdens runtime, wordt de fout terugvertaald naar de .phlo-regel die je hebt geschreven, op de foutpagina en in het Phlo Control Center.
De kosten zijn een build-stap. In de ontwikkeling verdwijnt het achter rebuild-on-request (X.6); in productie bouw je één keer.
21.4: De `obj` magische basis klasse
Elke getranspileerde klasse breidt obj uit: willekeurige gegevens via __get/__set, gebonden closures en berekende eigenschappen geschreven als _name() methoden, die zonder haakjes worden aangeroepen en bij de eerste toegang worden gecached. In .phlo transpileert prop now => time() naar een gecachte _now(). Eén toegangmodel vervangt getters, luie initialisatie en waarde-objecten; hetzelfde object dient als view model, record en configuratietas.
De kosten: magische toegang is minder statisch analyseerbaar dan expliciete eigenschappen, en het model vereist discipline met betrekking tot caches. De statische structuur caches in obj bevatten alleen de klassevorm, nooit aanvraag- of gebruikersspecifieke waarden, wat het veilig houdt in de worker-modus.
21.5: `phlo()` als een kleine service registry
phlo('MySQL') retourneert een gedeelde instantie; in .phlo bron transpileert %MySQL precies naar die aanroep. Elke klasse kan __handle() implementeren om zijn eigen identiteit te bepalen (singleton, multiton op argument, altijd nieuw) en ervoor kiezen om tussen worker-aanvragen te overleven. Je krijgt afhankelijkheidslookup zonder een containerframework, configuratie of annotaties, en de %name shorthand houdt aanroepplaatsen kort en doorzoekbaar.
Het eerlijke label is service locatie, niet injectie: afhankelijkheden zijn impliciet op de aanroepplaats. In ruil daarvoor is er nul bedrading, en het register zelf is een dozijn regels.
21.6: Herbouw op verzoek in ontwikkeling
Met build: true controleert Phlo of er wijzigingen in de bron zijn en bouwt het opnieuw voordat de aanvraag wordt afgehandeld, beperkt zodat de controle goedkoop is in een hete lus. De edit-refresh lus voelt geïnterpreteerd aan terwijl de runtime getranspileerd blijft, zonder een watcher-proces en zonder handmatige build.
De kosten: bouwen schrijft bestanden tijdens een aanvraag, wat onveilig is in een langlopende worker, dus build en thread zijn wederzijds exclusief. Ontwikkeling gebruikt on-demand builds; productie draait worker-modus op een release build. De splitsing is opzettelijk, geen beperking om omheen te werken.
21.7: Geen afhankelijkheden
De engine levert zijn eigen CSS-transpiler, JS-minifier, icon-sprite bouwer en SPA-runtime, plus meer dan 150 gebundelde resources in plaats van een pakketstructuur. Composer wordt ondersteund, maar is lui en optioneel. De engine heeft niets te auditen behalve zichzelf, upgrades op zijn eigen schema en blijft klein genoeg om in je hoofd te houden. Voor een platform waarvan de premisse leesbaarheid is, zou een vendor tree die premisse ondermijnen.
De kosten: Phlo herimplementeert dingen die volwassen bibliotheken al oplossen, dus die implementaties moeten getest worden en kunnen randgevallen hebben die een grote bibliotheek niet zou hebben. De inzet is dat een klein, eigendom oppervlak hier meer waard is dan breedte.
Zero dependencies is ook een standpunt in een vijftienjarige discussie. Het JavaScript-tijdperk heeft de backend naar steeds grotere engines en frameworks verplaatst, en afhankelijkheidsstructuren diep genoeg om hun eigen audittools nodig te hebben, waarmee problemen worden opgelost die een server-rendered stack nooit had: build chains, hydration, state synchronisatie. Phlo loopt opzettelijk de andere kant op, terug naar de techniek die het web al die tijd stilletjes heeft gedragen: PHP draait nog steeds meer dan 70% van alle websites waarvan de server-side taal bekend is (W3Techs). Phlo besteedt zijn innovatie aan de taal en de ontwikkelaarservaring, niet aan het herbouwen van infrastructuur die nooit het probleem was.
Één stem in die discussie verdient expliciete erkenning: Rich Harris. Svelte toonde aan dat een framework een compiler kan zijn: declaratieve broncode wordt het beste omgezet in eenvoudige, directe code tijdens de buildtijd, zodat het framework zelf meestal verdwijnt voordat het ooit in productie komt. Dat idee is een directe inspiratie voor Phlo. Waar Svelte de compiler naar de component bracht, neemt Phlo het over de stack: .phlo compileert naar leesbare PHP, CSS en JavaScript, en wat draait is output die je kunt openen en lezen, niet een runtime die je intentie interpreteert. De waardering is oprecht, ook al verschillen de conclusies: Svelte wedde op het JavaScript-ecosysteem, Phlo wedt tegen afhankelijkheid van één.
21.7.1 Expliciete resources, geen autoloading
Dezelfde voorkeur voor explicietheid regeert de resources. Een app verklaart wat het gebruikt in data/app.json; een resource die niet is verklaard, is simpelweg niet aanwezig, en het verwijzen ernaar faalt hard en vroeg in plaats van te worden opgeroepen door een autoloader. Dat is opzettelijk. Een resource is meer dan een klasse: het kan globale functies, frontend-assets en configuratie leveren, en PHP kan helemaal geen functies autoloaden, dus een luie loader zou slechts half één kunnen laden, waardoor de fout later en verder van de oorzaak komt. Magisch laden zou ook de manifest betekenisloos maken: je zou data/app.json niet meer kunnen lezen en weten waar een app uit bestaat, en de build zou niet langer een gesloten, complete bundel kunnen compileren.
Dus blijft de manifest de enige bron van waarheid en is een ontbrekende resource een duidelijke, onmiddellijke fout die aangeeft wat er ontbreekt. Het toevoegen van een resource is ook geen karwei: in de ontwikkeling toont het Phlo Control Center (bij /phlo wanneer build en debug aan zijn) de volledige catalogus, toont de vereisten tussen resources en bewerkt de resource-lijst in data/app.json voor je.
21.8: Zelf-gehoste eigendom
Een Phlo-app is een directory van bestanden op een server die je beheert. Het draait als één FrankenPHP-proces, blijft in het geheugen in worker-modus en beantwoordt verzoeken zonder dat er een meter per aanroep draait. De kosten zijn een server, niet een gebruiksrekening: dezelfde machine bedient je honderdste bezoeker en je honderdduizendste, en de regel op de factuur buigt niet omhoog met succes.
Dit is een bewuste afstand van de cloud en serverless standaard, waar de rekening het kleinst is precies wanneer je geen gebruikers hebt en groeit met elk verzoek zodra je dat wel hebt. Voor een product dat werkt, kan dat model groei in een aansprakelijkheid omzetten: hoe meer het wordt gebruikt, hoe meer het kost om draaiende te houden, soms voorbij het punt waar de cijfers nog logisch zijn. Phlo wedt de andere kant op. Je bezit de taaluitvoer (leesbaar PHP), de data (een bestand of een database die je beheert) en de machine waarop alles draait. Het Phlo Dashboard beheert dat als je vloot, niet als gehuurde capaciteit die je nooit ziet.
Zelf-gehost betekent niet onschalbaar. Een stateless PHP-toepassing laag achter een load balancer, met gedeelde staat in een database of cache, is de architectuur die de grootste sites op het web al meer dan 25 jaar draait. Phlo valt er rechtstreeks in: het transpileert naar gewone PHP op FrankenPHP, en worker-modus is share-nothing per verzoek, zodat je de toepassingslaag schaalt door meer identieke knooppunten achter de load balancer te draaien, tegen een voorspelbare kosten per knooppunt. Meerdere knooppunten hebben gedeelde sessiestaat nodig (wijs PHP's sessieopslag aan Redis of een database toe, of gebruik sticky sessions), en de database wordt de laag die het echte schaalwerk doet, replica's en partitionering, precies zoals in elke dergelijke stack. De toepassingslaag is het goedkope, gemakkelijke deel; de datalaag is waar de engineering plaatsvindt. De implementatiedocumenten behandelen de concrete multi-node setup.
De kosten: eigendom is ook verantwoordelijkheid. Je provisioneert de server, je past deze aan, je maakt de back-ups, je draagt de pager. Er is geen autoscaling naar nul en geen beheerde controlelaag die de operationele belasting absorbeert. De weddenschap is dat voor de meeste producten een voorspelbare server die je begrijpt beter is dan een elastische rekening die je niet kunt begrijpen.
21.9: Agent-eerst ontworpen
SKILL.md is een complete taal- en bouwreferentie geschreven zodat een AI-agent kan werken zonder voorafgaande kennis; de reflect:: CLI exposeert routes, views, de geparseerde structuur, zoek- en afhankelijkheidsgrafieken als JSON; apps houden een data/app.md scratchpad dat een agent eerst leest en daarna bijwerkt. Dezelfde eigenschappen die Phlo leesbaar maken voor jou (één gesloten lus, bron-gemapte fouten, een enkel vaardighedocument) maken het ook beheersbaar voor een agent, en het behandelen daarvan als een eersteklas doel vermenigvuldigt een klein team.
De kosten: SKILL.md en reflect:: maken deel uit van het contract. Een wijziging in de taal, de build of de CLI wordt pas doorgevoerd als de documentatie dit weerspiegelt. Die onderhoudsbelasting wordt opzettelijk geaccepteerd.
21.10: Wat Phlo niet is
Eerlijkheid over de grenzen:
- Een jong ecosysteem. Geen marktplaats voor plugins, geen Stack Overflow-archief. De meegeleverde bronnen en de gids vormen het ecosysteem.
- Meningsvol van constructie. De strengheid van de lijnparser, de regel voor lege regels in views, punten in plaats van underscores in bestandsnamen: deze zijn niet configureerbaar.
- Geen dependency injection.
%instanceis service locatie; als je expliciete constructor wiring wilt, zal Phlo impliciet aanvoelen. - Realtime is een handler broker, geen streaming engine. Phlo Realtime dispatcht elk evenement naar je PHP hooks via de Phlo Daemon, standaard eenmalig (één proces per evenement, eenvoudig en robuust) of via een resident worker pool wanneer je de doorvoer nodig hebt. Het schaalt door het toevoegen van workers en nodes, maar het blijft een per-evenement model, geen low-latency bus voor duizenden berichten per seconde per socket.
- Dev en productie zijn verschillende modi. Rebuild-on-request en worker mode sluiten elkaar per ontwerp uit; je kunt niet beide tegelijk hebben.
Als die beperkingen passen, krijg je de beloning die dit hoofdstuk beschrijft: één taal en één mentaal model, verticaal geïntegreerd van je eerste view tot je hele fleet.