18: Filosofie

Dit hoofdstuk legt uit waarom Phlo is gebouwd zoals het is: de opzettelijke afwegingen achter de parser, de compiler, 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 daar stilletjes tegenin. 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 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 gewone PHP die jij bezit. Het draait op een machine die jij controleert, tegen een kostprijs 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.

18.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:

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.

18.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.

18.3: Compileren naar leesbare PHP

.phlo compileert 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.

18.4: De `obj` magische basis klasse

Elke gecompileerde 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 compileert 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 verzoek- of gebruikersspecifieke waarden, wat het veilig houdt in de worker-modus.

18.5: `phlo()` als een kleine service registry

phlo('MySQL') retourneert een gedeelde instantie; in .phlo broncode compileert %MySQL precies naar die aanroep. Elke klasse kan __handle() implementeren om zijn eigen identiteit te bepalen (singleton, multiton op basis van 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.

18.6: Herbouw op verzoek in ontwikkeling

Met build: true controleert Phlo of er wijzigingen in de bron zijn en compileert 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 gecompileerd 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.

18.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 de 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.

18.8: Zelf-gehoste eigendom

Een Phlo-app is een map met 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 het draaiende te houden, soms voorbij het punt waar de cijfers nog logisch zijn. Phlo wedt de andere kant op. Je bezit de taaloutput (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 compileert 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, 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.

18.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.

18.10: Wat Phlo niet is

Eerlijkheid over de grenzen:

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.

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