Kort gezegd: Objectgeoriënteerd programmeren (OOP) bundelt gegevens en de bijbehorende functies in klassen. PHP biedt hiervoor klassen, abstracte klassen, interfaces, traits en sinds PHP 8.1 enums. Met PHP 8.0 tot 8.4 kwamen veel taalmiddelen erbij, zoals constructor promotion, readonly, property hooks en asymmetrische zichtbaarheid. Belangrijk voor de beveiliging: goed ingekapselde code is gemakkelijker te controleren, en magische methoden maken onveilige deserialisatie gevaarlijk. Tegen lekken in de interpreter zoals PHP2Shell helpt OOP niet.
Wat objectgeoriënteerd programmeren in PHP betekent
In plaats van losse functies en globale variabelen te gebruiken, beschrijft een klasse een ding uit het vakgebied: een bestelling, een klant, een factuur. Ze legt vast welke gegevens erbij horen (eigenschappen) en wat men ermee kan doen (methoden). Een object is een concreet exemplaar van die klasse.
Voor beslissers heeft dat een praktische waarde: objectgeoriënteerde code met duidelijke klassen is beter te testen, te controleren en over te dragen aan dienstverleners. Oude PHP-toepassingen uit veel afzonderlijke scripts met globale variabelen zijn daarentegen moeilijk te onderhouden en foutgevoelig bij upgrades.
Een centrale gedachte is inkapseling: een klasse geeft naar buiten alleen de methoden vrij die anderen echt nodig hebben en beschermt haar interne toestand. Een bestelling kan dan bijvoorbeeld alleen via een methode als betaald worden gemarkeerd die vooraf controleert of dat überhaupt is toegestaan. Zulke regels op één plek bundelen is ook voor de beveiliging een winst.
De bouwstenen in een overzicht
| Bouwsteen | Doel | Kort voorbeeld |
|---|---|---|
| Klasse | bouwplan voor objecten met eigenschappen en methoden | class Rechnung { ... } |
| abstracte klasse | gemeenschappelijke basis, niet direct te instantiëren | abstract class Zahlart { ... } |
| Interface | contract: welke methoden een klasse moet aanbieden | interface Versandfaehig { ... } |
| Trait | herbruikbare methoden voor klassen zonder gemeenschappelijke bovenliggende klasse | trait MitZeitstempel { ... } |
| Enum | vaste set toegestane waarden als eigen type, sinds PHP 8.1 | enum Status { case Offen; ... } |
Zichtbaarheden (public, protected, private) regelen wie toegang heeft tot eigenschappen en methoden. Klassen worden in namespaces georganiseerd en via een autoloader geladen; hoe dat werkt, toont de pagina Namespaces en autoloading.
Modern PHP: de nieuwigheden van 8.0 tot 8.4
De volgende taalmiddelen zijn gedocumenteerd in de PHP-handleiding, respectievelijk in de release-aankondigingen:
| Versie | Nieuwigheid |
|---|---|
| 8.0 | constructor promotion, nullsafe-operator ?->, ::class op objecten |
| 8.1 | readonly-eigenschappen, enums, new in initialisaties, final voor klasseconstanten |
| 8.2 | readonly-klassen; dynamische eigenschappen gelden als verouderd |
| 8.3 | attribuut #[\Override], getypeerde klasseconstanten |
| 8.4 | property hooks, asymmetrische zichtbaarheid, new zonder omsluitende haakjes |
Een voorbeeld dat meerdere van deze middelen combineert:
<?php
declare(strict_types=1);
enum Status: string
{
case Offen = 'offen';
case Bezahlt = 'bezahlt';
}
final class Bestellung
{
public function __construct(
public readonly int $id,
public private(set) Status $status = Status::Offen, // vanaf PHP 8.4
) {}
public function alsBezahltMarkieren(): void
{
$this->status = Status::Bezahlt;
}
}
$b = new Bestellung(42);
$b->alsBezahltMarkieren();
echo $b->status->value; // bezahlt
$s = Status::tryFrom('storniert'); // null in plaats van een fout
readonly voorkomt dat de ID na het aanmaken wordt gewijzigd. private(set) staat lezen van buitenaf toe, maar schrijven alleen binnen de klasse. Zulke garanties in de code maken fouten onwaarschijnlijker die anders pas in bedrijf opvallen. De typen daarachter legt de pagina Het typesysteem van PHP uit.
Upgradevallen in objectgeoriënteerde code
Voor oudere toepassingen zijn twee wijzigingen bijzonder relevant. Sinds PHP 8.2.0 is het aanmaken van dynamische eigenschappen verouderd, dus van eigenschappen die in de klasse niet zijn gedeclareerd, tenzij de klasse het attribuut #[\AllowDynamicProperties] draagt. Oudere code gebruikt dat vaak onbewust en vult de logs dan met aanwijzingen. Bovendien moeten getypeerde eigenschappen volgens de handleiding vóór de eerste leesactie zijn geïnitialiseerd, anders werpt PHP een Error.
Nuttig is het attribuut #[\Override] uit PHP 8.3: het markeert een methode als overschrijving van een methode van de bovenliggende klasse. Bestaat die methode niet meer, bijvoorbeeld na een hernoeming in een bibliotheek, dan meldt PHP een fout in plaats van de methode stilletjes in het luchtledige te laten lopen. Zulke controles maken upgrades beter planbaar; bij vastgelopen oude projecten helpt onze migratie naar een ondersteunde PHP-versie.
Objecten en geheugen
Objecten worden in PHP doorgegeven via identificaties (handles). Geeft men een object aan een functie, dan werkt die met hetzelfde object, niet met een kopie. Dat is efficiënt, maar leidt gemakkelijk tot kringverwijzingen, bijvoorbeeld wanneer een bestelling haar posities kent en elke positie weer haar bestelling. Zulke cycli ruimt de referentietelling alleen niet op; daarvoor heeft PHP een eigen garbage collector. Details staan op de pagina Geheugenbeheer in PHP.
OOP en beveiliging: magische methoden en deserialisatie
PHP kent magische methoden die automatisch worden aangeroepen, zoals __construct, __destruct, __toString, __get of __wakeup. Dat is praktisch, maar heeft een keerzijde: als een toepassing vreemde gegevens met unserialize() weer in objecten omzet, kan een aanvaller bepalen welke klassen ontstaan en zo bestaande code in magische methoden activeren. Hoe u dat voorkomt, beschrijft de gids Onveilige deserialisatie in PHP. Kort gezegd: gebruik voor gegevensuitwisseling json_encode() en json_decode() en gebruik unserialize() alleen voor eigen, betrouwbare gegevens, bij voorkeur met de optie allowed_classes.
Bij PHP2Shell helpt goede objectgeoriënteerde code daarentegen niet. CVE-2026-109618 en CVE-2026-109619 zitten in de interpreter, en bij mod_php is volgens het PHP-team een exploit getoond voordat toepassingscode draait. Verplicht is de update naar PHP 8.5.12, 8.4.27, 8.3.36 of 8.2.35 en de herstart van alle PHP-processen.
Hoe helpt PHP SOS concreet?
- Wij beoordelen de opbouw van uw toepassing en laten zien welke onderdelen een upgrade naar een ondersteunde PHP-versie bemoeilijken.
- Wij zoeken gericht naar risicovolle patronen zoals
unserialize()op vreemde gegevens en gevaarlijke magische methoden. - Wij controleren eigen ontwikkelingen in het kader van een beveiligingsaudit en penetratietest.
- Wij voeren de PHP-update door, starten alle workers opnieuw en testen de toepassing daarna.
Veelgestelde vragen
Is PHP een objectgeoriënteerde taal?
PHP ondersteunt zowel procedurele als objectgeoriënteerde code. Frameworks, CMS-kernen en shopsystemen zijn tegenwoordig echter overwegend objectgeoriënteerd opgebouwd, met klassen, interfaces en namespaces.
Wat is het verschil tussen een interface en een abstracte klasse?
Een interface beschrijft alleen welke methoden een klasse moet aanbieden. Een abstracte klasse kan daarnaast al code en eigenschappen bevatten, maar kan niet direct worden geïnstantieerd. Een klasse kan meerdere interfaces hebben, maar slechts één bovenliggende klasse.
Sinds wanneer zijn er enums in PHP?
Enumeraties kwamen met PHP 8.1. Ze vervangen verzamelingen van constanten door een eigen type dat alleen de gedefinieerde gevallen toestaat. Backed enums hebben daarnaast een int- of string-waarde.
Waarom zijn magische methoden beveiligingsrelevant?
Methoden zoals __destruct of __wakeup roept PHP automatisch aan, bijvoorbeeld bij het deserialiseren van gegevens. Komen vreemde gegevens ongecontroleerd in unserialize() terecht, dan kan dat onverwachte processen in bestaande klassen in gang zetten.