---
title: 'PHP 5.5: Generators, finally, password_* API & Migration | DevSense'
description: "Guide de mise à niveau PHP 5.5 : découvrez les générateurs économes en mémoire (yield), les blocs try-catch-finally, l'API native de hachage de mots de passe, la syntaxe ClassName::class et comment migrer depuis mysql et preg_replace /e dépréciés."
faq:
    - { question: "Qu'est-ce qu'un générateur en PHP 5.5 ?", answer: "Un générateur est une fonction spéciale qui produit des valeurs une par une à la demande à l'aide du mot-clé `yield`, vous permettant de parcourir de grands ensembles de données avec une utilisation minimale de la mémoire." }
    - { question: 'Comment la nouvelle API de hachage de mots de passe améliore-t-elle la sécurité ?', answer: 'Elle fournit des fonctions simples et natives (`password_hash` et `password_verify`) qui génèrent automatiquement des grains de sel (salts) sécurisés et utilisent bcrypt par défaut, éliminant les implémentations maison et faibles.' }
    - { question: 'Que fait ClassName::class ?', answer: 'Il se résout en le nom complet sous forme de chaîne de la classe (par exemple, `App\Models\User`), ce qui permet le refactoring dans les IDE et évite les erreurs associées aux noms de classe saisis manuellement sous forme de chaînes de caractères.' }
    - { question: 'Quel est le rôle de Zend OPcache dans PHP 5.5 ?', answer: "Zend OPcache est désormais intégré nativement avec PHP. Il stocke le bytecode précompilé des scripts dans la mémoire partagée, accélérant considérablement les temps d'exécution de PHP en évitant la compilation à chaque requête." }
published: '2026-05-31'
---
# PHP 5.5 : Efficacité mémoire et sécurité native

Lire un fichier journal de 5 Go ligne par ligne à l'aide de `file()` peut épuiser la mémoire de votre serveur en quelques secondes, générant la redoutable erreur « Allowed memory size exhausted ». PHP 5.5 a résolu ce problème définitivement en introduisant les générateurs (`yield`), permettant le traitement de flux à la volée tout en préservant la mémoire.

Avant PHP 5.5, les développeurs devaient analyser de grands fichiers ou ensembles de données en créant d'immenses tableaux en mémoire, ou écrire des objets Iterator complexes et verbeux. De plus, le hachage sécurisé des mots de passe était un mélange d'implémentations maison à base de MD5/SHA256 avec du sel, et le nettoyage des ressources après des erreurs était fastidieux car PHP ne disposait pas de bloc `finally`.

> [!IMPORTANT]
> PHP 5.5 a introduit des optimisations de mémoire révolutionnaires grâce aux générateurs et a standardisé la cryptographie avec l'API intégrée de hachage de mots de passe (Password Hashing API).

---

## Table des matières
* [Générateurs (`yield`)](#generators)
* [Le bloc `finally`](#finally)
* [API native de hachage de mots de passe](#password-api)
* [`array_column()` & `::class`](#helpers)
* [Intégration de Zend OPcache](#opcache)
* [Erreurs courantes](#common-mistakes)
* [Recettes pratiques](#practical-recipes)
* [Changements non rétrocompatibles](#backward-incompatible)
* [🧠 Questions d'auto-évaluation](#self-check)

---

<a id="generators"></a>
## Générateurs (`yield`)

Les générateurs calculent les valeurs à la volée plutôt que de construire et de renvoyer un tableau géant.

```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);
    }
}
```

* **Pourquoi c'est important** : Parcourir de grands fichiers, des résultats de base de données ou des séquences infinies consomme une quantité de mémoire infime et constante (souvent moins de quelques kilo-octets), quelle que soit la taille du jeu de données.
* **Conséquence** : Le traitement par lots et les pipelines de données deviennent extrêmement performants et stables sous de lourdes charges de travail.

---

<a id="finally"></a>
## Le bloc `finally`

PHP 5.5 ajoute le mot-clé `finally` à la structure `try-catch`. Le code contenu dans `finally` s'exécute indépendamment du fait qu'une exception ait été levée ou non, même si `return` est appelé dans les blocs `try` ou `catch`.

```php
// app/Services/DatabaseClient.php
public function processTransaction()
{
    $this->db->connect();
    try {
        $this->db->execute();
    } catch (\Exception $e) {
        $this->logError($e);
    } finally {
        // Ceci est TOUJOURS exécuté, évitant les fuites de ressources
        $this->db->disconnect();
    }
}
```

* **Pourquoi c'est important** : Simplifie les opérations de nettoyage telles que la fermeture des pointeurs de fichiers, des connexions de base de données ou le déverrouillage de fichiers.

---

<a id="password-api"></a>
## API native de hachage de mots de passe

Arrêtez de générer manuellement le sel de sécurité. Les nouvelles fonctions de mots de passe rendent leur sécurisation infaillible.

```php
// app/Services/AuthService.php
// Hacher un mot de passe à l'aide de bcrypt (PASSWORD_DEFAULT)
$hash = password_hash($password, PASSWORD_DEFAULT);

// Vérifier le mot de passe lors de la connexion
if (password_verify($password, $hash)) {
    // Si le paramètre de coût (cost) ou l'algorithme change, mettre à jour le hachage
    if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
        $newHash = password_hash($password, PASSWORD_DEFAULT);
        // Sauvegarder $newHash dans la base de données
    }
}
```

> [!NOTE]
> `password_hash` génère automatiquement un grain de sel cryptographique sécurisé et le stocke à l'intérieur de la chaîne de hachage renvoyée, ce qui signifie que vous n'avez pas besoin d'une colonne de base de données distincte pour les sels.

---

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

PHP 5.5 introduit deux outils hautement pratiques :

### 1. `array_column()`
Extrait une seule colonne d'un tableau multidimensionnel ou d'objets.

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

### 2. `ClassName::class`
Renvoie le nom complet avec espace de noms d'une classe sous forme de chaîne de caractères.

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

---

<a id="opcache"></a>
## Intégration de Zend OPcache

Zend OPcache fait désormais partie du noyau de PHP. Il stocke le bytecode PHP compilé en mémoire, de sorte que les fichiers n'ont pas besoin d'être analysés et compilés à chaque requête.

* **Pourquoi c'est important** : Augmente les performances en production de 2 à 3 fois selon la taille du framework.
* **Conséquence** : Les développeurs doivent mettre en œuvre des stratégies de vidage de cache (comme appeler `opcache_reset()` ou redémarrer le gestionnaire de processus) lors des déploiements.

---

<a id="common-mistakes"></a>
## ⚠️ Erreurs courantes

### 1. Utilisation du modificateur dangereux `/e` dans `preg_replace`
Le modificateur `/e` évalue la chaîne de remplacement comme du code PHP, ce qui entraîne des vulnérabilités d'exécution de code à distance (RCE). Il est déprécié dans PHP 5.5.

```php
// app/Helpers/StringHelper.php
// ❌ Déprécié & hautement non sécurisé !
$output = preg_replace('/(\w+)/e', 'strtoupper("$1")', $text);

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

### 2. Oubli de nettoyer les ressources des générateurs lors d'une sortie de boucle prématurée
Si vous sortez d'une boucle de générateur (break), les ressources telles que les fichiers ouverts peuvent rester ouvertes à moins d'être enveloppées dans des blocs `try/finally` à l'intérieur du générateur.

```php
// app/Services/FileReader.php
// ❌ Dangereux : si la boucle s'arrête prématurément, fclose() n'est jamais exécuté
function readData($file) {
    $fh = fopen($file, 'r');
    while($line = fgets($fh)) yield $line;
    fclose($fh);
}

// ✅ Approche correcte
function readDataSafe($file) {
    $fh = fopen($file, 'r');
    try {
        while($line = fgets($fh)) yield $line;
    } finally {
        fclose($fh); // Garanti de s'exécuter lors de la destruction du générateur
    }
}
```

### 3. S'appuyer sur l'ancienne extension `mysql`
Les fonctions `mysql_connect()` sont dépréciées dans PHP 5.5.

```php
// app/Database/LegacyDb.php
// ❌ Déprécié en PHP 5.5, génère un avertissement E_DEPRECATED
$conn = mysql_connect('localhost', 'user', 'pass');

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

---

<a id="practical-recipes"></a>
## Recettes pratiques

### Attentes vs Réalité : `finally` et instructions de retour (Returns)

Que se passe-t-il lorsque le bloc `try` et le bloc `finally` renvoient tous deux des valeurs ?

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

// Attente : Renvoie "Retour depuis try"
// Réalité :
echo testFinally(); // Sortie : Retour depuis finally
```

> [!WARNING]
> Si vous renvoyez une valeur à l'intérieur du bloc `finally`, elle écrasera toute valeur renvoyée dans les blocs `try` ou `catch`. Évitez de placer des instructions `return` dans un bloc `finally`.

---

<a id="backward-incompatible"></a>
## Changements non rétrocompatibles

1. **Dépréciation du modificateur `/e` dans `preg_replace`** : Génère des avertissements ; vous devez utiliser `preg_replace_callback()`.
2. **Dépréciation de l'extension `mysql`** : Génère des avertissements `E_DEPRECATED` lors des connexions.
3. **`empty()` sur des expressions** : Avant PHP 5.5, `empty()` n'acceptait que des variables (ex. `empty($x)`). Il accepte désormais des expressions comme `empty(trim($x))`. Bien que cela ne casse rien directement, cela rend les anciennes solutions de contournement obsolètes.
4. **Modifications du format de `pack()` et `unpack()`** : Certains changements d'alignement sur 64 bits peuvent affecter la sérialisation binaire.

---

## 🧠 Questions d'auto-évaluation

1. **Vrai ou Faux ?** Une fonction génératrice renvoie un objet `Generator` qui implémente l'interface `Iterator`.
2. Si une exception est levée dans un bloc `try` et n'est capturée par aucun bloc `catch`, le code à l'intérieur du bloc `finally` s'exécute-t-il tout de même ?
3. Que se passe-t-il si vous tentez de passer directement un tableau de paramètres de coût à `password_verify()` ?
4. **Vrai ou Faux ?** `ClassName::class` fonctionne à l'exécution même si la classe n'est pas chargée ou n'existe pas.

<details>
<summary><b>Afficher les réponses</b></summary>

1. **Vrai.** Les générateurs renvoient une instance de la classe `Generator`, ce qui permet de les utiliser directement dans des boucles `foreach`.
2. **Oui.** L'exécution du bloc `finally` est garantie avant que l'exception ne remonte et n'arrête l'exécution du script.
3. Rien, car `password_verify` n'accepte que deux arguments : le mot de passe en clair et le hachage. Il lit l'algorithme et les paramètres de coût directement à partir de la chaîne de hachage elle-même.
4. **Vrai.** `::class` est résolu au moment de la compilation. Le moteur ne tente pas de charger automatiquement la classe ou de vérifier son existence ; il renvoie simplement la chaîne de caractères contenant l'espace de noms complet.
</details>