---
title: 'PHP 8.2: What’s New — Types, Readonly Classes, Security & Migration | DevSense'
description: 'Leitfaden für PHP 8.2: Readonly-Klassen, eigenständige null/false/true Typen, DNF-Typen, #[SensitiveParameter], Random-Erweiterung, Missbilligung dynamischer Eigenschaften und BC-Breaks ab PHP 8.1.'
faq:
    - { question: 'Was sind schreibgeschützte Klassen (Readonly Classes) in PHP 8.2?', answer: 'Eine schreibgeschützte Klasse markiert implizit alle ihre Eigenschaften als schreibgeschützt (readonly). Alle Eigenschaften müssen typisiert sein und die Klasse unterstützt keine dynamischen Eigenschaften. Sie kann nur von anderen schreibgeschützten Klassen erben.' }
    - { question: 'Wie verbessert #[SensitiveParameter] die Anwendungssicherheit?', answer: 'Das Attribut #[SensitiveParameter] schwärzt sensible Werte (wie Passwörter, Schlüssel oder Token) in Stacktraces, um ein versehentliches Durchsickern in Logdateien oder Fehlerausgaben zu verhindern.' }
    - { question: 'Was ist DNF (Disjunktive Normalform) in PHP 8.2?', answer: 'DNF ermöglicht es Entwicklern, Union- und Schnittmengentypen in einem standardisierten Format zu kombinieren, wie z. B. `(Countable&Traversable)|null` für Methoden, die komplexe Strukturen oder null akzeptieren.' }
    - { question: 'Warum sind dynamische Eigenschaften in PHP 8.2 veraltet?', answer: 'Dynamische Eigenschaften sind veraltet, um Laufzeitfehler durch Tippfehler in Eigenschaftsnamen zu vermeiden. Klassen müssen ihre Eigenschaften deklarieren, `#[AllowDynamicProperties]` verwenden oder `__set()`/`__get()` implementieren.' }
published: '2026-05-31'
---
# PHP 8.2: Hauptmerkmale

Praxisnotizen für Teams, die von PHP 8.1.x auf 8.2.x migrieren: Spracherweiterungen, sicherheitsorientierte Attribute, strengere String-Verarbeitung und die veralteten Features (Deprecations), die Sie vor dem nächsten Versionssprung beheben sollten.

## Inhalt
* [#[SensitiveParameter] und sicherere Stacktraces](#sensitive-parameter)
* [Readonly-Klassen](#readonly-classes)
* [Eigenständige Typen (`null`, `false`, `true`) und DNF](#standalone-types-dnf)
* [Konstanten in Traits & Enums in konstanten Ausdrücken](#traits-constants)
* [INI: `error_log_mode`](#error-log-mode)
* [Random-Erweiterung](#random-extension)
* [Bemerkenswerte Erweiterungs-Updates (cURL, PCRE)](#extension-updates)
* [Rückwärtskompatibilität und BC-Breaks (Migrationshinweise)](#backward-incompatible)
* [Veraltete Features (beheben, bevor sie zu Fehlern werden)](#deprecations)
* [Erweiterungen & Laufzeit-Hinweise](#extensions-notes)
* [Häufige Fehler](#common-mistakes)
* [Selbsttest-Quiz](#self-test-quiz)

---

PHP 8.2 lenkt die Sprache konsequent in Richtung expliziter Typisierung und struktureller Sicherheit. Mit der Einführung von Readonly-Klassen und DNF-Typen (Disjunktive Normalform) erhalten Entwickler eine feingranulare Kontrolle über die Unveränderlichkeit von Objekten und komplexe Typdeklarationen. Die Sicherheit wird zudem auf Sprachebene verankert, indem vertrauliche Daten explizit mit `#[SensitiveParameter]` markiert werden können, um zu verhindern, dass sie in Stacktraces auftauchen. Gleichzeitig führt diese Version erhebliche Missbilligungen ein – vor allem für dynamische Eigenschaften –, um Fehler bereits vor dem Produktivbetrieb abzufangen. Hier ist Ihr Übergangsleitfaden zu PHP 8.2.

<a id="sensitive-parameter"></a>
## #[SensitiveParameter] und sicherere Stacktraces

Das Attribut `#[\SensitiveParameter]` markiert Parameter, die in Stacktraces und Debugging-Ausgaben unkenntlich gemacht werden müssen. Dies reduziert die Gefahr, dass Anmeldedaten versehentlich in Protokolldateien oder auf Fehlerseiten landen.

> [!NOTE]
> **Wussten Sie schon?**
> Das Attribut `#[SensitiveParameter]` arbeitet nativ mit der Standard-Exception-Trace-Ausgabe von PHP zusammen. Generiert PHP einen Stacktrace, wird der Parameterwert durch ein `SensitiveParameterValue`-Objekt ersetzt. Dadurch wird die ursprüngliche Zeichenfolge in den Logs komplett maskiert!

```php
// app/Services/DatabaseService.php
function connect(#[\SensitiveParameter] string $password): void
{
    throw new RuntimeException('fail');
}
```

Kombinieren Sie dieses Feature mit einer disziplinierten Protokollierung und geben Sie niemals rohe Exceptions in Produktionsumgebungen aus.

### Praktisches Rezept: Geheimnisse an Systemgrenzen markieren

Verwenden Sie `#[\SensitiveParameter]` bei Parametern, die in Exceptions landen könnten (API-Clients, Auth-Helper). Es hält Stacktraces nützlich, ohne Anmeldedaten offenzulegen.

```php
// app/Clients/ApiClient.php
final class ApiClient
{
    public function __construct(
        private readonly string $baseUrl,
        #[\SensitiveParameter] private readonly string $token,
    ) {}
}
```

---

<a id="readonly-classes"></a>
## Readonly-Klassen

Eine Klasse kann als `readonly` deklariert werden. Dadurch werden **alle** ihre Instanzeigenschaften schreibgeschützt (readonly) und erfordern eine Initialisierung bei der Instanziierung (entspricht dem manuellen Zuweisen von `readonly` für jede einzelne Eigenschaft).

> [!NOTE]
> **Wussten Sie schon?**
> Eine schreibgeschützte Klasse verhindert automatisch dynamische Eigenschaften! Sie müssen dafür nicht einmal das Attribut `#[AllowDynamicProperties]` verwenden, da der Versuch, einer schreibgeschützten Klasse eine dynamische Eigenschaft hinzuzufügen, sofort einen Fehler auslöst.

```php
// app/DTO/Point.php
readonly class Point
{
    public function __construct(
        public int $x,
        public int $y,
    ) {}
}
```

Verwenden Sie dieses Feature für unveränderliche Value Objects und DTOs, bei denen der gesamte Objektgraph nach der Konstruktion eingefroren sein soll.

---

<a id="standalone-types-dnf"></a>
## Eigenständige Typen (`null`, `false`, `true`) und DNF

PHP 8.2 erlaubt **`null`**, **`false`** und **`true`** als eigenständige Typen in Typdeklarationen (nicht mehr nur als Teil von Union-Typen wie in älteren Versionen).

**DNF (Disjunctive Normal Form / Disjunktive Normalform)** erlaubt es Ihnen, **Union-** und **Schnittmengentypen (Intersection Types)** in einer normierten Form zu kombinieren, z. B. `(A&B)|null`. Dies ist nützlich für präzise APIs, ohne die Unterstützung von Nullwerten aufzugeben.

```php
// app/Services/ExportService.php
function accepts((Countable&Traversable)|null $c): void {}
```

---

<a id="traits-constants"></a>
## Konstanten in Traits & Enums in konstanten Ausdrücken

* **Konstanten in Traits** sind nun zulässig – hilfreich für gemeinsam genutzte Konfigurationen, ohne eine zusätzliche Basisklasse erzwingen zu müssen.
* **Enum-Eigenschaften in konstanten Ausdrücken**: Sie können Enums und deren Eigenschaften an Stellen referenzieren, an denen konstante Ausdrücke erforderlich sind. Dies ermöglicht eine flexiblere Konfiguration zur Kompilierzeit.

---

<a id="error-log-mode"></a>
## INI: `error_log_mode`

Die INI-Direktive **`error_log_mode`** legt die Dateiberechtigungen für die Fehlerprotokolldatei (Error Log) fest, wenn PHP diese neu erstellt – nützlich für gehärtete Serverumgebungen (um z. B. weltweit lesbare Protokolldateien zu verhindern).

---

<a id="random-extension"></a>
## Random-Erweiterung

Die **Random**-Erweiterung konsolidiert und erweitert die APIs zur Generierung von Zufallszahlen. Sie bietet klarere Optionen für Zufallszahlengeneratoren (RNG) und verringert typische Stolpersteine älterer Funktionen. Bevorzugen Sie diese Erweiterung für neuen Code, der reproduzierbare Seeds, bessere Algorithmen oder Testbarkeit benötigt.

### Praktisches Rezept: `Randomizer` für Tokens und Stichproben

```php
// app/Services/TokenGenerator.php
$engine = new Random\Engine\Mt19937(random_int());
$randomizer = new Random\Randomizer($engine);
$token = $randomizer->getBytesFromString('0123456789abcdef', 32);
```

Nutzen Sie im Testing eine Engine mit festem Seed, um Zufallswerte deterministisch und damit testbar zu machen. Verwenden Sie für Sicherheitsrelevantes (wie Passwörter oder Geheimnisse) eine kryptografisch sichere Engine.

---

<a id="extension-updates"></a>
## Bemerkenswerte Erweiterungs-Updates (cURL, PCRE)

* **cURL**: `CURLINFO_EFFECTIVE_METHOD` gibt die tatsächlich genutzte HTTP-Methode zurück; `curl_upkeep()` hilft bei der Aufrechterhaltung von Verbindungen.
* **PCRE**: Der Modifikator **`n` (NO_AUTO_CAPTURE)** sorgt dafür, dass einfache Klammergruppen `()` standardmäßig nicht erfassend (non-capturing) sind, es sei denn, sie sind benannt – praktisch für komplexe Regex-Muster mit weniger nummerierten Rückwärtsreferenzen.

---

<a id="backward-incompatible"></a>
## Rückwärtskompatibilität und BC-Breaks (Migrationshinweise)

### Datum & Zeit

* `DateTime::createFromImmutable()` und `DateTimeImmutable::createFromMutable()` verwenden nun einen **vorläufigen `static`** Rückgabetyp.
* Relative Datumsformate: Das Vorzeichen bei Zahlenangaben erlaubt keine doppelten Zeichen mehr (z. B. `+-2` ist ungültig).

### Standard-Bibliothek (Hohe Auswirkung)

* **Lokale-unabhängige ASCII-Groß-/Kleinschreibung**: `strtolower()`, `strtoupper()`, `lcfirst()`, `ucfirst()`, `ucwords()` und ähnliche Funktionen sind **nicht mehr abhängig von der System-Locale**. Sie verhalten sich nun standardmäßig wie die `"C"`-Locale. Verwenden Sie **mbstring** für lokalitätsspezifische Zeichensatzkonvertierungen.
* **`str_split('')`** gibt nun ein leeres Array `[]` zurück (zuvor `[""]`).
* **`glob()` / `GlobIterator`**: Unter `open_basedir` haben sich die Warnungen und Rückgabewerte bei leerem Ergebnis verändert – prüfen Sie Verzeichnisscans in restriktiven Hosting-Umgebungen.
* **`FilesystemIterator`**: `SKIP_DOTS` ist nicht mehr fest voreingestellt; setzen Sie Flags explizit, falls Sie sich auf das alte Standardverhalten verlassen haben.
* **`ksort` / `krsort`**: `SORT_REGULAR` nutzt nun konsistent die numerischen String-Regeln von PHP 8.
* **`var_export()`**: Führende Backslashes bei Klassennamen werden nicht mehr weggelassen (vollständig qualifizierte Klassennamen).

### ODBC / PDO_ODBC

Benutzername und Passwort werden beim Anhängen an Verbindungszeichenfolgen **maskiert** (escaped). Dies behebt SQL-Injections und fehlerhafte Verbindungszeichenfolgen. Überprüfen Sie Ihre Integrationstests gegen echte DSNs.

### SPL

Mehrere Methoden von `SplFileObject` erzwingen nun strengere Signaturen; die Rückgabetypen einiger Methoden wurden präzisiert (z. B. `hasChildren`, `getChildren`).

---

<a id="deprecations"></a>
## Veraltete Features (beheben, bevor sie zu Fehlern werden)

### Dynamische Eigenschaften

Das Erstellen von **dynamischen Eigenschaften** auf beliebigen Klassen ist veraltet, es sei denn, die Klasse verwendet das Attribut **`#[\AllowDynamicProperties]`** (oder erbt von Klassen wie `stdClass`, die dies erlauben). Bevorzugen Sie die explizite Deklaration von Eigenschaften, `WeakMap` für externe Metadaten oder die magischen Methoden `__get()`/`__set()`.

### Eingeschränkte Callables

Callables, die zwar von `call_user_func()` akzeptiert werden, aber nicht direkt über `$callable()` aufgerufen werden können (z. B. `"self::method"`, `"parent::method"` oder bestimmte Array-Muster), sind veraltet. Normalisieren Sie diese auf Muster wie `Foo::bar` oder `[Class::class, 'method']`.

### String-Interpolation

Die String-Interpolation im Stil von `"${var}"` / `"${expr}"` ist veraltet. Verwenden Sie stattdessen `"{$var}"` oder eine explizite String-Konkatenation.

### Sonstiges

* **`utf8_encode` / `utf8_decode`**: Veraltet (verwenden Sie stattdessen `mb_convert_encoding` oder `iconv`).

---

<a id="common-mistakes"></a>
## ⚠️ Häufige Fehler

Hier sind typische Fehlerquellen beim Wechsel auf PHP 8.2:

### 1. Erstellen dynamischer Eigenschaften
In PHP 8.2 löst das Zuweisen von Werten an nicht deklarierte Eigenschaften einer Klasse eine Deprecation-Warnung aus. In PHP 9.0 wird dies zu einem Fatal Error.

```php
// app/Services/UserService.php
// SCHLECHT: Erzeugt in PHP 8.2 eine Deprecation-Warnung
class UserService {
    public string $name;
}

$service = new UserService();
$service->email = 'user@example.com'; // Deprecation Warning: Creation of dynamic property is deprecated
```

### 2. Nutzung der veralteten Syntax für String-Interpolation
Die alte Syntax `${var}` ist in PHP 8.2 veraltet.

```php
// app/Services/NotificationService.php
// SCHLECHT: Löst eine Deprecation-Warnung aus
$name = 'Alice';
echo "Hallo ${name}"; // Deprecation Warning

// GUT: Nutzen Sie die Standard-Syntax mit geschweiften Klammern
echo "Hallo {$name}";
```

### 3. Vererbung bei Readonly-Klassen
Eine `readonly`-Klasse darf nur von anderen `readonly`-Klassen erben.

```php
// app/DTO/Point3D.php
class Point2D {}

// SCHLECHT: Fatal Error: Readonly class Point3D cannot extend non-readonly class Point2D
readonly class Point3D extends Point2D {}
```

---

<a id="self-test-quiz"></a>
## Selbsttest-Quiz

Testen Sie Ihr Wissen über PHP 8.2.

### Frage 1: Was passiert, wenn Sie eine Klasse in PHP 8.2 als `readonly` deklarieren?
* A) Alle Eigenschaften werden implizit als `readonly` markiert, müssen aber nicht zwingend typisiert sein.
* B) Sie können der Klasse keine dynamischen Eigenschaften hinzufügen und alle Eigenschaften müssen typisiert sein.
* C) Sie darf jede beliebige normale Klasse erweitern, aber normale Klassen dürfen nicht von ihr erben.

<details>
<summary>Antworten anzeigen</summary>

**Richtige Antwort: B**  
Das Deklarieren einer Klasse als `readonly` bewirkt, dass alle Eigenschaften implizit readonly sind und einen Typ deklarieren müssen. Zudem sind dynamische Eigenschaften für solche Klassen gesperrt und sie können nur von anderen readonly Klassen erben.
</details>

### Frage 2: Welche Interpolations-Syntax löst in PHP 8.2 eine Deprecation-Warnung aus?
* A) `"Hallo {$name}"`
* B) `"Hallo ${name}"`
* C) `"Hallo " . $name`

<details>
<summary>Antworten anzeigen</summary>

**Richtige Antwort: B**  
Die String-Interpolation im Stil von `${var}` ist veraltet und erzeugt eine Warnung. Verwenden Sie stattdessen `{$var}`.
</details>

---

## Zusammenfassung

PHP 8.2 steuert die Sprache konsequent in Richtung expliziter Typisierung und struktureller Sicherheit. Durch die Einführung von Readonly-Klassen und DNF-Typen (Disjunktive Normalform) gewinnen Entwickler eine feine Kontrolle über Objekt-Unveränderlichkeit und komplexe Typen.