Navigation
 Startseite
 Fachbücher
 Anzeigenmarkt
 Forum
 Webmaster News
 Script Newsletter
 Push Meldungen
 Kontakt
 Script Installation
 Php
 Php Tutorials
 Lernpfade
 Webhoster Vergleich
 Impressum

Community-Bereich
 kostenlos Registrieren
 Anmelden
 Benutzerliste

Script Datenbank
 Script Archiv
 Script Top 20
 Screenshots
 Testberichte

Suche
 

Unsere Php Scripts
 Counter Script
 Umfrage Script
 Bilder Upload Script
 Terminverwaltung
 Simple PHP Forum
 RSS Grabber

Tools und Generatoren
 .htpasswd Generator
 md5 Generator
 base64 Generator
 Markdown to HTML
 Colorpicker
 Unix timestamp Tool
 Unit Test Generator
 TLD Liste
 Webkatalog‑Verzeichnis

Artfiles.de
Bietet Serviceorientierte...
https://www.Artfiles.de
Webspace-Mieten.d...
Webhosting mit Plesk aus Erfurt: Vier...
https://www.Webspace-Mieten.de
 
 
 

PHP Property Hooks in PHP 8.4: Getter, Setter und das RFC

Sie befinden sich: Home > Php Tutorial > PHP Property Hooks in PHP 8...

PHP Property Hooks in PHP 8.4: Getter, Setter und das RFC
Veröffentlicht am:
23.10.2026
Hits / Besucher:
3
Sprache:
  Deutsch
Tutorial Art:
eigenes
Eingetragen von:
Merkliste:
 
Beschreibung

Eine Kundenklasse mit privatem $email, dazu getEmail() und setEmail() mit Prüfung: Für eine einzige Eigenschaft kommen schnell zwanzig Zeilen zusammen. Genau dieses Muster zeigt das Tutorial zu Klassen und Objekten als klassischen Weg zur Kapselung. Seit PHP 8.4 sitzt die Logik an der Eigenschaft selbst. PHP Property Hooks hängen einen get-Block und einen set-Block an die Property, und von außen bleibt es bei der gewohnten Zuweisung $kunde->email = '...'.

Illustration zum Tutorial: PHP Property Hooks in PHP 8.4: Getter, Setter und das RFC

Ob eine Property mit Hook ihren Wert speichert oder bei jedem Lesen neu berechnet, sieht man ihr auf den ersten Blick nicht an.

Was sind PHP Property Hooks? Idee und RFC

Ein Hook ist Code, der an einer Property hängt und Zugriffe abfängt. Der get-Hook läuft beim Lesen, der set-Hook beim Schreiben. In Lehrbüchern heißen Setter auch Mutator-Methoden; PHP Property Hooks übernehmen deren Aufgabe, ohne dass eine Methode entsteht, die der Aufrufer kennen muss. Das Feature kam mit PHP 8.4. Das RFC dazu stammt von Ilija Tovilo und Larry Garfield und orientiert sich nach eigener Aussage am stärksten an Kotlin, mit Anleihen bei C# und Swift.

So sieht die Kundenklasse aus der Einleitung mit einem set-Hook aus:

<?php

class Kunde
{
public string $email {
set {
$neu = strtolower(trim($value));
$ok = filter_var(
$neu,
FILTER_VALIDATE_EMAIL
);
if ($ok === false) {
throw new InvalidArgumentException(
"Keine E-Mail-Adresse: $value"
);
}
$this->email = $neu;
}
}
}

$kunde = new Kunde();
$kunde->email = ' Info@Example.ORG ';
echo $kunde->email; /* info@example.org */

Innerhalb des Hooks greift $this->email direkt auf den gespeicherten Wert zu und löst den Hook nicht erneut aus. Jede andere Zuweisung, auch eine aus einer Methode derselben Klasse, läuft dagegen durch den set-Hook. Welcher Weg bei einem Zugriff genommen wird, zeigt das Schema:

flowchart TD
    A[Zugriff auf die Property] --> B{Lesen?}
    B -->|ja| C{get-Hook da?}
    C -->|ja| D[get-Hook liefert Wert]
    C -->|nein| E[gespeicherter Wert]
    B -->|nein, schreiben| F{set-Hook da?}
    F -->|ja| G[set-Hook prüft und wandelt]
    G --> H[speichern oder Exception]
    F -->|nein| I{Property virtuell?}
    I -->|ja| J[Error, read-only]
    I -->|nein| K[Wert direkt speichern]

Syntax der Property Hooks in PHP

Es gibt genau zwei Hooks, get und set. Beide kennen eine Kurzform mit Pfeil und eine Blockform mit geschweiften Klammern:

class Example

{
public string $name {
get => expression;
set => expression;
}
}

/* Property hooks were added to PHP 8.4.
This feature lets a class intercept property
access: reading the property calls get,
writing it calls set. For simple logic they
replace getter and setter methods (mutator
methods), which are verbose.

get => expr short get, returns expr
get { return; } block get, must return
set => expr short set, stores expr
set { ... } block set, uses $value
set(T $v) { ... } own name, wider type ok

A property is virtual when no hook
reads or writes $this->name itself.
A virtual property has no default value.
With property hooks, most getters and setters
become plain property access. Developers wrap
the logic around the property, callers keep
the cleaner $obj->name syntax.

The design is inspired by languages like
Kotlin, with ideas from C# and Swift. */

Im set-Hook steht der neue Wert in $value, ohne dass man ihn deklariert. Wer einen eigenen Namen will, schreibt set(string $neu); der Typ darf dabei weiter sein als der der Property, etwa string|DateTimeImmutable für eine Datums-Property, die auch Text annimmt. Ein unverträglicher Typ endet in Type of parameter $value of hook X::$n::set must be compatible with property type. Die Kurzform set => ausdruck speichert das Ergebnis des Ausdrucks immer in der eigenen Property. Andere Hooks als get und set gibt es nicht, ein isset => ... bricht mit einem Parse error ab.

PHP 8.4 vorausgesetzt: der Parse error davor

Läuft der Server noch mit PHP 8.3, kommen PHP Property Hooks gar nicht erst zur Ausführung. Gemessen mit dem offiziellen Docker-Image für 8.3, an der Kundenklasse vom Anfang:

Parse error: syntax error, unexpected token "{",

expecting "," or ";" in ... on line 4

Die Meldung nennt keine Version, deshalb sucht man den Fehler leicht im eigenen Code. Steht der Hook in einer Konstruktor-Promotion, endet die Meldung stattdessen auf expecting ")". Eine Versionsprüfung hilft nur, wenn sie in einer anderen Datei steht als die Klasse mit den Hooks. PHP parst eine Datei vollständig, bevor die erste Zeile läuft, und eine Prüfung oben in derselben Datei kommt nie zum Zug:

<?php

/* index.php, ohne eigene Hooks */
if (PHP_VERSION_ID < 80400) {
exit('Property Hooks brauchen PHP 8.4');
}

require __DIR__ . '/src/Kunde.php';

Bei vielen Hostern lässt sich die Version im Kundenmenü umstellen. Unter PHP 8.5 verhalten sich alle Beispiele dieses Tutorials wie unter 8.4.

Der set-Hook: Werte beim Schreiben prüfen

Der häufigste Einsatz von PHP Property Hooks ist eine Prüfung, die ungültige Werte gar nicht erst in das Objekt lässt. Wirft der set-Hook eine Exception, bleibt der alte Wert stehen:

<?php

class Konto
{
public int $saldo = 0 {
set {
if ($value < 0) {
throw new InvalidArgumentException(
'Saldo darf nicht negativ sein'
);
}
$this->saldo = $value;
}
}
}

$konto = new Konto();
$konto->saldo = 50;

try {
$konto->saldo = -5;
} catch (InvalidArgumentException $e) {
echo $e->getMessage();
}
echo $konto->saldo; /* 50 */

Der Typ der Property gilt auch für den Hook. Ein Text wie 'abc' scheitert mit TypeError: Konto::$saldo::set(): Argument #1 ($value) must be of type int, string given. Ohne declare(strict_types=1) wandelt PHP dagegen '42' still in die Zahl 42 um, genau wie bei einem Funktionsparameter.

Hooks in der Konstruktor-Promotion

Hooks lassen sich auch an einen Parameter der Konstruktor-Promotion schreiben. Die Grundlagen zu Typen und Konstruktor-Promotion erklärt das Tutorial zu Typed Properties. Der set-Hook läuft schon beim Erzeugen des Objekts:

<?php

class Produkt
{
public function __construct(
public string $sku {
set => strtoupper(trim($value));
},
public float $preis = 0.0,
) {}
}

$p = new Produkt(' ab-12 ', 9.9);
echo $p->sku; /* AB-12 */

Einen solchen Parameter mit nur einem get-Hook nimmt PHP zwar an, er scheitert aber bei new mit Error: Property A::$x is read-only. Er ist virtuell, und der Konstruktor versucht, ihm einen Wert zuzuweisen.

Virtuelle Properties: berechnen statt speichern

PHP Property Hooks können auch Werte liefern, die nirgends gespeichert sind. Eine Property ist virtuell, wenn keiner ihrer Hooks auf $this->name der eigenen Property zugreift. Sie hat dann keinen eigenen gespeicherten Wert im Objekt und eignet sich für Werte, die sich aus anderen ableiten. Ein Bruttopreis, der nie vom Nettopreis abweichen darf, ist der typische Fall:

<?php

class Preis
{
public function __construct(
public float $netto,
public float $steuersatz = 0.19,
) {}

public float $brutto {
get => round(
$this->netto * (1 + $this->steuersatz),
2
);
}
}

$p = new Preis(100.0);
echo $p->brutto; /* 119 */

Schreiben lässt sich $brutto nicht, der Versuch endet in Error: Property Preis::$brutto is read-only. Einen Standardwert verbietet PHP für virtuelle Properties ebenfalls. Bei der Ausgabe verhalten sich die Funktionen unterschiedlich, und das überrascht beim ersten Export:

Ausgabe virtueller Wert enthalten?
json_encode() ja, {"netto":100,"steuersatz":0.19,"brutto":119}
get_object_vars() ja
foreach über das Objekt ja
var_export() ja
var_dump() und print_r() nein
Cast in ein Array nein
serialize() nein

Für Umrechnungen in beide Richtungen taugt die Kurzform des set-Hooks nicht. Wer set => $this->celsius = ... schreibt, bekommt keine virtuelle Property: Die Kurzform speichert das Ergebnis der Zuweisung zusätzlich in der eigenen Property, isVirtual() meldet dann false. Mit der Blockform bleibt sie virtuell:

<?php

class Temperatur
{
public float $celsius = 0.0;

public float $fahrenheit {
get => $this->celsius * 9 / 5 + 32;
set {
$this->celsius = ($value - 32) * 5 / 9;
}
}
}

$t = new Temperatur();
$t->fahrenheit = 212;
echo $t->celsius; /* 100 */

Grenzen von PHP Property Hooks

Einige Kombinationen mit PHP Property Hooks lehnt die Sprache grundsätzlich ab. Alle Meldungen sind unter Windows und Linux mit PHP 8.4 geprüft:

Fall Meldung Ausweg
readonly mit Hook, auch in einer readonly class Hooked properties cannot be readonly Asymmetric Visibility, siehe unten
static mit Hook Cannot declare hooks for static property statische Methode
$obj->liste[] = $x Indirect modification of ... is not allowed Array kopieren und neu zuweisen
Referenz mit &$obj->n Indirect modification of Z::$n is not allowed Wert zurückgeben statt Referenz
unset($obj->x) Cannot unset hooked property Q::$x Property nullable machen
Standardwert an virtueller Property Cannot specify default value for virtual hooked property Wert im get-Hook liefern
&get zusammen mit set Get hook of backed property ... may not return by reference auf einen der beiden verzichten

Bei readonly liegt der Grund in der Prüfung selbst. PHP erkennt einen noch beschreibbaren readonly-Wert daran, dass der gespeicherte Wert nicht initialisiert ist. Eine virtuelle Property hat gar keinen gespeicherten Wert, und ein get-Hook würde verwischen, was „initialisiert“ überhaupt bedeutet. Das RFC macht die Kombination deshalb zu einem Fehler beim Übersetzen.

Die Array-Zeile trifft in der Praxis am häufigsten. Für $b->positionen[] = 'Kabel' bräuchte PHP eine Referenz auf das gespeicherte Array, und die gibt eine Property mit Hook nicht heraus. Das gilt schon bei einem einzelnen get-Hook. Der Ausweg ist unspektakulär:

<?php

class Bestellung
{
public array $positionen = [] {
set => array_values($value);
}
}

$b = new Bestellung();
$liste = $b->positionen;
$liste[] = 'Kabel';
$b->positionen = $liste; /* set-Hook läuft */

Wer oft anhängt, gibt der Klasse eine Methode hinzufuegen(). Ein &get ohne set-Hook lässt das Anhängen zwar wieder zu, umgeht dann aber jede Prüfung. Anders beim Hochzählen: $z->n++ funktioniert, weil PHP dafür erst den get-Hook und dann den set-Hook aufruft.

Vererbung: parent::$x::get() und final

Eine Kindklasse kann die Hooks ihrer Elternklasse erweitern. Der Aufruf läuft nicht über eine Methode, sondern über den Namen der Property:

<?php

class Feld
{
public string $titel = '' {
set => trim($value);
}
}

class PflichtFeld extends Feld
{
public string $titel = '' {
set {
parent::$titel::set(ucwords($value));
}
get => parent::$titel::get() . ' *';
}
}

$f = new PflichtFeld();
$f->titel = ' name ';
echo $f->titel; /* Name * */

Den Standardwert = '' wiederholt die Kindklasse mit Absicht. Ohne ihn verliert die neu deklarierte Property ihren Startwert, und der erste Lesezugriff endet in Typed property ... must not be accessed before initialization. Soll ein Hook gar nicht überschrieben werden, steht final set in der Elternklasse. Eine Kindklasse, die es trotzdem versucht, scheitert mit Cannot override final property hook Basis::$x::set().

Property Hooks in Interfaces und abstrakten Klassen

Wie Properties in Interfaces und abstrakte Properties in das jeweilige Konzept passen, zeigen die Tutorials zu Interfaces und zu abstrakten Klassen. Für PHP Property Hooks bringen beide eigene Regeln mit. Ein Interface verlangt keine bestimmte Umsetzung, sondern nur, dass gelesen oder geschrieben werden kann:

<?php

interface HatName
{
public string $name { get; }
}

class Kategorie implements HatName
{
public string $name = 'Kabel';
}

class Kunde implements HatName
{
public function __construct(
public string $vorname,
public string $nachname,
) {}

public string $name {
get => "$this->vorname $this->nachname";
}
}

Beide Klassen erfüllen den Vertrag, und eine readonly-Property aus der Konstruktor-Promotion täte es ebenso. Verlangt das Interface { get; set; }, reicht ein reiner get-Hook nicht mehr. Die Meldung spricht dann von einer abstrakten Methode, weil PHP den fehlenden set-Hook wie eine solche behandelt: Class E contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (HatWert::$wert::set). Eine Property ohne Hook-Angabe ist in Interfaces nicht erlaubt (Interfaces may only include hooked properties), und eine private Umsetzung lehnt PHP ab.

In einer abstrakten Klasse gilt dasselbe mit abstract davor. abstract public string $typ { get; } verlangt von jeder Kindklasse eine lesbare Property, und eine schlichte public string $typ = 'PKW'; erfüllt das bereits. Fehlt sie, meldet PHP Class Rad contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Fahrzeug::$typ::get).

PHP Property Hooks, Getter und Setter im Vergleich

PHP Property Hooks ersetzen Getter und Setter nicht überall. Oft passt einer von vier anderen Wegen besser:

Ansatz Passt für Haken
Property Hooks Prüfen, Bereinigen, Berechnen beim Zugriff kein readonly, keine Arrays per []
Getter und Setter aufwendige Logik, mehrere Parameter, sprechende Namen viel Code für wenig Inhalt
readonly Werte, die nach dem Konstruktor nie wechseln auch die Klasse selbst kann nicht mehr schreiben
public private(set) außen lesbar, nur innen schreibbar keine Prüfung beim Schreiben
__get() und __set() dynamische Namen, Altcode unsichtbar für IDE und statische Analyse

Die Asymmetric Visibility mit public private(set) kam ebenfalls mit PHP 8.4 und ist oft die bessere Wahl als PHP Property Hooks, wenn nur der Schreibzugriff von außen verboten werden soll. Ein Hook wäre dafür ein Umweg. Der Schreibversuch von außen meldet Cannot modify private(set) property Ticket::$status from global scope. Wer von magischen Methoden umsteigt, kann beides mischen: __get() wird für eine Property mit Hook nicht aufgerufen, für unbekannte Namen weiterhin.

Zur Laufzeit gemessen mit fünf Millionen Lesezugriffen:

Zugriff Windows 8.4.8 Linux 8.4.17
einfache Property 50 ms 23 ms
Getter-Methode 145 ms 72 ms
get-Hook 129 ms 62 ms

Ein Hook ist also etwas schneller als ein Getter, aber gut zweieinhalbmal so langsam wie der direkte Zugriff. Für eine Property ohne Logik gehört deshalb kein Hook dazu.

Für Werkzeuge, die Objekte aus der Datenbank befüllen, liefert Reflection alles Nötige. hasHooks() und isVirtual() geben Auskunft über die Property, getRawValue() und setRawValue() lesen und schreiben am Hook vorbei. Ein Hydrator vermeidet so, dass jede gespeicherte Zeile erneut durch die Prüfung läuft:

<?php

$prop = new ReflectionProperty(Kunde::class, 'email');
$prop->setRawValue($kunde, 'Alt@Example.ORG');

echo $kunde->email;
/* Alt@Example.ORG, der set-Hook lief nicht */

Fazit

PHP Property Hooks verlegen Prüfung und Berechnung dorthin, wo der Wert liegt. Ein set-Hook bereinigt oder lehnt ab, ein get-Hook formatiert oder berechnet, und eine Property ohne Zugriff auf den eigenen Wert speichert gar nichts. Voraussetzung ist PHP 8.4 auf dem Server, sonst steht ein Parse error vor allem anderen.

Die meisten Überraschungen kommen von drei Stellen: Die Kurzform von set speichert immer, Arrays lassen sich nicht per [] erweitern, und readonly verträgt sich nicht mit Hooks. Wo nur der Schreibzugriff von außen stört, reicht private(set), und wo eine Property keine Logik trägt, bleibt sie am schnellsten ohne Hook.

 


 

Kommentare (0)

Noch keine Kommentare. Sei der Erste!

Melde dich an, um einen Kommentar zu schreiben.
Bücherregal mit drei Büchern: 'PHP 4 - Grundlagen und Profiwissen' von Hanser Verlag, 'Webdesign in a Nutshell' von O'Reilly Verlag, und 'Webgestaltung' von Galileo Computing.