---
title: 'PHP 5.5: Generators, finally, password_* API & Migration | DevSense'
description: 'Upgrade-Leitfaden für PHP 5.5: Lernen Sie speichereffiziente Generatoren (yield), try-catch-finally-Blöcke, die native Password Hashing API, die ClassName::class-Syntax kennen und wie Sie von veraltetem mysql und preg_replace /e migrieren.'
faq:
    - { question: 'Was ist ein Generator in PHP 5.5?', answer: 'Ein Generator ist eine spezielle Funktion, die Werte bei Bedarf einzeln mittels des `yield`-Schlüsselworts zurückgibt. Dies ermöglicht es, große Datenmengen mit minimalem Speicheraufwand zu durchlaufen.' }
    - { question: 'Wie verbessert die neue Password Hashing API die Sicherheit?', answer: 'Sie bietet einfache, native Funktionen (`password_hash` und `password_verify`), die automatisch sichere Salts generieren und standardmäßig bcrypt verwenden. Dadurch werden unsichere Eigenbau-Hashing-Implementierungen überflüssig.' }
    - { question: 'Was bewirkt ClassName::class?', answer: 'Es wird in den vollqualifizierten String-Namen der Klasse aufgelöst (z. B. `App\Models\User`), was IDE-Refactoring ermöglicht und Tippfehler bei der manuellen Angabe von Klassennamen als String verhindert.' }
    - { question: 'Welche Rolle spielt Zend OPcache in PHP 5.5?', answer: 'Zend OPcache ist nun nativ in PHP integriert. Es speichert vorkompilierten Bytecode von Skripten im gemeinsam genutzten Speicher und beschleunigt die Ausführungszeit von PHP erheblich, da die Kompilierung bei jedem Request entfällt.' }
published: '2026-05-31'
---
# PHP 5.5: Speichereffizienz & Native Sicherheit

Das zeilenweise Einlesen einer 5 GB großen Logdatei mittels `file()` kann den Speicher Ihres Servers in Sekundenschnelle erschöpfen und zu dem gefürchteten Fehler „Allowed memory size exhausted“ führen. PHP 5.5 hat dieses Problem dauerhaft gelöst, indem Generatoren (`yield`) eingeführt wurden, die eine speicherschonende Stream-Verarbeitung im laufenden Betrieb ermöglichen.

Vor PHP 5.5 mussten Entwickler große Dateien oder Datensätze verarbeiten, indem sie riesige Arrays im Arbeitsspeicher aufbauten oder komplexe, langatmige Iterator-Objekte schrieben. Darüber hinaus war sicheres Passwort-Hashing ein Chaos aus selbstgebauten MD5/SHA256-Salts, und das Bereinigen von Ressourcen nach Fehlern gestaltete sich umständlich, da PHP kein `finally`-Block besaß.

> [!IMPORTANT]
> PHP 5.5 führte bahnbrechende Speicheroptimierungen über Generatoren ein und standardisierte die Kryptographie mit der integrierten Password Hashing API.

---

## Inhalt
* [Generatoren (`yield`)](#generators)
* [Der `finally`-Block](#finally)
* [Native Password Hashing API](#password-api)
* [`array_column()` & `::class`](#helpers)
* [Zend OPcache-Integration](#opcache)
* [Häufige Fehler](#common-mistakes)
* [Praktische Rezepte](#practical-recipes)
* [Rückwärtskompatibilität und BC-Breaks](#backward-incompatible)
* [🧠 Selbsttest-Fragen](#self-check)

---

<a id="generators"></a>
## Generatoren (`yield`)

Generatoren berechnen Werte im laufenden Betrieb, anstatt ein riesiges Array aufzubauen und zurückzugeben.

```php
// app/Services/LogReader.php
function readLines(string $filePath): Generator
{
    $handle = fopen($filePath, 'r');
    if (!$handle) {
        return;
    }
    try {
        while (($line = fgets($handle)) !== false) {
            yield trim($line);
        }
    } finally {
        fclose($handle);
    }
}
```

* **Warum es wichtig ist**: Das Durchlaufen großer Dateien, Datenbankergebnisse oder unendlicher Sequenzen verbraucht unabhängig von der Datensatzgröße nur eine konstant winzige Menge an Speicher (oft weniger als ein paar Kilobyte).
* **Auswirkung**: Batch-Verarbeitung und Daten-Pipelines werden unter hoher Last extrem performant und stabil.

---

<a id="finally"></a>
## Der `finally`-Block

PHP 5.5 erweitert die `try-catch`-Struktur um das Schlüsselwort `finally`. Code innerhalb von `finally` wird immer ausgeführt – unabhängig davon, ob eine Exception geworfen wurde oder nicht, und selbst dann, wenn ein `return` innerhalb von `try` oder `catch` aufgerufen wird.

```php
// app/Services/DatabaseClient.php
public function processTransaction()
{
    $this->db->connect();
    try {
        $this->db->execute();
    } catch (\Exception $e) {
        $this->logError($e);
    } finally {
        // Wird IMMER ausgeführt, um Ressourcenlecks zu vermeiden
        $this->db->disconnect();
    }
}
```

* **Warum es wichtig ist**: Vereinfacht Aufräumarbeiten wie das Schließen von Datei-Handles, Datenbankverbindungen oder das Entsperren von Dateien.

---

<a id="password-api"></a>
## Native Password Hashing API

Schluss mit selbstgebauter Salt-Generierung. Die neuen Passwort-Funktionen machen das Absichern von Passwörtern kinderleicht.

```php
// app/Services/AuthService.php
// Passwort mit bcrypt hashen (PASSWORD_DEFAULT)
$hash = password_hash($password, PASSWORD_DEFAULT);

// Passwort beim Login verifizieren
if (password_verify($password, $hash)) {
    // Falls sich der Cost-Parameter oder Algorithmus ändert, Hash aktualisieren
    if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
        $newHash = password_hash($password, PASSWORD_DEFAULT);
        // $newHash in DB speichern
    }
}
```

> [!NOTE]
> `password_hash` generiert automatisch ein sicheres kryptographisches Salt und speichert es innerhalb des zurückgegebenen Hash-Strings ab. Das bedeutet, dass Sie keine separate Datenbankspalte für Salts benötigen.

---

<a id="helpers"></a>
## `array_column()` & `::class`

PHP 5.5 führt zwei äußerst praktische Werkzeuge ein:

### 1. `array_column()`
Extrahiert eine einzelne Spalte aus einem mehrdimensionalen Array oder Objekten.

```php
// app/Services/Report.php
$users = [
    ['id' => 1, 'name' => 'Alice'],
    ['id' => 2, 'name' => 'Bob']
];
$ids = array_column($users, 'id'); // [1, 2]
```

### 2. `ClassName::class`
Gibt den vollqualifizierten Namespace-Namen einer Klasse als String zurück.

```php
// app/Services/Container.php
use App\Models\User;
echo User::class; // "App\Models\User"
```

---

<a id="opcache"></a>
## Zend OPcache-Integration

Zend OPcache ist nun fest in den PHP-Core integriert. Es speichert vorkompilierten PHP-Bytecode im Speicher, sodass Dateien nicht bei jedem Request neu analysiert und kompiliert werden müssen.

* **Warum es wichtig ist**: Steigert die Performance in Produktionsumgebungen je nach Framework-Größe um das 2- bis 3-fache.
* **Auswirkung**: Entwickler müssen Strategien zum Leeren des Caches (z. B. den Aufruf von `opcache_reset()` oder den Neustart des Prozessmanagers) beim Deployment implementieren.

---

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

### 1. Verwendung des gefährlichen `/e`-Modifiers in `preg_replace`
Der Modifikator `/e` evaluiert den Ersetzungsstring als PHP-Code, was zu Remote-Code-Execution-Sicherheitslücken (RCE) führen kann. Er ist in PHP 5.5 veraltet.

```php
// app/Helpers/StringHelper.php
// ❌ Veraltet & höchst unsicher!
$output = preg_replace('/(\w+)/e', 'strtoupper("$1")', $text);

// ✅ Richtiges Vorgehen
$output = preg_replace_callback('/(\w+)/', function($m) {
    return strtoupper($m[1]);
}, $text);
```

### 2. Fehlende Freigabe von Ressourcen, wenn Generatoren vorzeitig abbrechen
Wenn Sie eine Generator-Schleife vorzeitig abbrechen (break), bleiben geöffnete Ressourcen wie Dateien möglicherweise geöffnet, es sei denn, sie sind innerhalb des Generators in `try/finally`-Blöcke gehüllt.

```php
// app/Services/FileReader.php
// ❌ Gefährlich: Wenn die Schleife abbricht, wird fclose() nie ausgeführt
function readData($file) {
    $fh = fopen($file, 'r');
    while($line = fgets($fh)) yield $line;
    fclose($fh);
}

// ✅ Richtiges Vorgehen
function readDataSafe($file) {
    $fh = fopen($file, 'r');
    try {
        while($line = fgets($fh)) yield $line;
    } finally {
        fclose($fh); // Wird garantiert ausgeführt, wenn der Generator zerstört wird
    }
}
```

### 3. Vertrauen auf die alte `mysql`-Erweiterung
Die `mysql_connect()`-Funktionen sind in PHP 5.5 veraltet.

```php
// app/Database/LegacyDb.php
// ❌ Veraltet in PHP 5.5, wirft E_DEPRECATED
$conn = mysql_connect('localhost', 'user', 'pass');

// ✅ Richtiges Vorgehen
$conn = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
```

---

<a id="practical-recipes"></a>
## Praktische Rezepte

### Erwartung vs. Realität: `finally` und Rückgabewerte (Returns)

Was passiert, wenn sowohl der `try`-Block als auch der `finally`-Block Werte zurückgeben?

```php
// app/Demo/FinallyDemo.php
function testFinally(): string
{
    try {
        return "Return aus try";
    } finally {
        return "Return aus finally";
    }
}

// Erwartung: Gibt "Return aus try" zurück
// Realität:
echo testFinally(); // Ausgabe: Return aus finally
```

> [!WARNING]
> Wenn Sie innerhalb des `finally`-Blocks einen Wert zurückgeben, überschreibt dieser alle in `try` oder `catch` zurückgegebenen Werte. Vermeiden Sie es, `return`-Anweisungen in `finally` zu platzieren.

---

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

1. **Veralten des `preg_replace` `/e`-Modifiers**: Wirft Warnungen; stattdessen muss `preg_replace_callback()` verwendet werden.
2. **Veralten der `mysql`-Erweiterung**: Wirft `E_DEPRECATED`-Warnungen bei Verbindungsaufbauten.
3. **`empty()` auf Ausdrücke**: Vor PHP 5.5 akzeptierte `empty()` nur Variablen (z. B. `empty($x)`). Jetzt werden Ausdrücke wie `empty(trim($x))` unterstützt. Obwohl dies kein direkter BC-Break ist, macht es alte Workarounds überflüssig.
4. **Formatänderungen bei `pack()` und `unpack()`**: Bestimmte Änderungen beim 64-Bit-Alignment können die binäre Serialisierung beeinflussen.

---

## 🧠 Selbsttest-Fragen

1. **Richtig oder Falsch?** Eine Generator-Funktion gibt ein `Generator`-Objekt zurück, welches das `Iterator`-Interface implementiert.
2. Wenn eine Exception im `try`-Block geworfen und von keinem `catch`-Block abgefangen wird, wird der Code im `finally`-Block trotzdem ausgeführt?
3. Was passiert, wenn Sie versuchen, ein Array von Cost-Parametern direkt an `password_verify()` zu übergeben?
4. **Richtig oder Falsch?** `ClassName::class` funktioniert zur Laufzeit selbst dann, wenn die Klasse nicht geladen ist oder nicht existiert.

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

1. **Richtig.** Generatoren geben eine Instanz der `Generator`-Klasse zurück, wodurch sie direkt in `foreach`-Schleifen verwendet werden können.
2. **Ja.** Es ist garantiert, dass der `finally`-Block ausgeführt wird, bevor die Exception nach oben gereicht wird und die Skriptausführung abbricht.
3. Nichts, da `password_verify` nur zwei Argumente akzeptiert: das Klartext-Passwort und den Hash. Die Algorithmus- und Cost-Parameter werden direkt aus dem Hash-String selbst ausgelesen.
4. **Richtig.** `::class` ist eine Auflösung zur Kompilierzeit. Es wird kein Autoloading versucht und die Existenz der Klasse wird nicht geprüft; es wird lediglich der Namespace-String zurückgegeben.
</details>