---
title: 'PHP 5.5: Generators, finally, password_* API & Migration | DevSense'
description: "Guida all'aggiornamento di PHP 5.5: scopri i generatori efficienti per la memoria (yield), i blocchi try-catch-finally, l'API nativa per il password hashing, la sintassi ClassName::class e come migrare dalle funzionalità deprecate mysql e preg_replace /e."
faq:
    - { question: "Cos'è un Generatore in PHP 5.5?", answer: 'Un generatore è una funzione speciale che restituisce i valori uno alla volta su richiesta utilizzando la parola chiave `yield`, consentendo di scorrere dataset di grandi dimensioni con un consumo minimo di memoria.' }
    - { question: 'In che modo la nuova API Password Hashing migliora la sicurezza?', answer: 'Fornisce funzioni semplici e native (`password_hash` e `password_verify`) che generano automaticamente salt sicuri e utilizzano bcrypt per impostazione predefinita, eliminando le implementazioni casalinghe e deboli.' }
    - { question: 'Cosa fa ClassName::class?', answer: 'Si risolve nel nome completo della classe sotto forma di stringa (es. `App\Models\User`), il che consente il refactoring negli IDE ed evita errori associati alla digitazione manuale delle stringhe dei nomi delle classi.' }
    - { question: 'Qual è il ruolo di Zend OPcache in PHP 5.5?', answer: 'Zend OPcache è ora integrato nativamente con PHP. Memorizza il bytecode precompilato degli script nella memoria condivisa, accelerando significativamente i tempi di esecuzione di PHP evitando la compilazione ad ogni richiesta.' }
published: '2026-05-31'
---
# PHP 5.5: Efficienza della memoria e sicurezza nativa

Leggere un file di log da 5 GB riga per riga utilizzando `file()` può esaurire la memoria del server in pochi secondi, generando il temuto errore \"Allowed memory size exhausted\". PHP 5.5 ha risolto questo problema introducendo i generatori (`yield`), che consentono un'elaborazione dei flussi a basso consumo di memoria.

Prima di PHP 5.5, gli sviluppatori dovevano analizzare file o dataset di grandi dimensioni creando array giganti in memoria, oppure scrivendo oggetti Iterator complessi e logorroici. Inoltre, il password hashing sicuro era un insieme caotico di salt MD5/SHA256 implementati manualmente e la pulizia delle risorse dopo gli errori era complessa a causa della mancanza di un blocco `finally` in PHP.

> [!IMPORTANT]
> PHP 5.5 ha introdotto ottimizzazioni rivoluzionarie per la memoria tramite i generatori e ha standardizzato la crittografia con l'API integrata Password Hashing API.

---

## Indice
* [Generatori (`yield`)](#generators)
* [Il blocco `finally`](#finally)
* [API nativa per il Password Hashing](#password-api)
* [`array_column()` e `::class`](#helpers)
* [Integrazione di Zend OPcache](#opcache)
* [Errori comuni](#common-mistakes)
* [Ricette pratiche](#practical-recipes)
* [Modifiche non retrocompatibili](#backward-incompatible)
* [🧠 Domande di autovalutazione](#self-check)

---

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

I generatori calcolano i valori al volo anziché compilare e restituire un array gigante.

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

* **Perché è importante**: Scorrere file di grandi dimensioni, risultati di database o sequenze infinite richiede una quantità di memoria costante e minima (spesso inferiore a pochi kilobyte), indipendentemente dalle dimensioni del dataset.
* **Conseguenza**: L'elaborazione in batch e le pipeline di dati diventano estremamente performanti e stabili anche sotto carichi di lavoro intensi.

---

<a id="finally"></a>
## Il blocco `finally`

PHP 5.5 aggiunge la parola chiave `finally` alla struttura `try-catch`. Il codice all'interno di `finally` viene eseguito indipendentemente dal fatto che sia stata generata o meno un'eccezione, anche se all'interno del blocco `try` o `catch` viene chiamato `return`.

```php
// app/Services/DatabaseClient.php
public function processTransaction()
{
    $this->db->connect();
    try {
        $this->db->execute();
    } catch (\Exception $e) {
        $this->logError($e);
    } finally {
        // Viene eseguito SEMPRE, evitando perdite di risorse
        $this->db->disconnect();
    }
}
```

* **Perché è importante**: Semplifica le operazioni di pulizia come la chiusura dei puntatori a file, delle connessioni al database o il rilascio dei blocchi sui file.

---

<a id="password-api"></a>
## API nativa per il Password Hashing

Basta con la generazione manuale dei salt. Le nuove funzioni per le password rendono sicura la memorizzazione in modo infallibile.

```php
// app/Services/AuthService.php
// Esegui l'hashing di una password usando bcrypt (PASSWORD_DEFAULT)
$hash = password_hash($password, PASSWORD_DEFAULT);

// Verifica la password al momento del login
if (password_verify($password, $hash)) {
    // Se il parametro di costo o l'algoritmo cambiano, aggiorna l'hash
    if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
        $newHash = password_hash($password, PASSWORD_DEFAULT);
        // Salva $newHash nel database
    }
}
```

> [!NOTE]
> `password_hash` genera automaticamente un salt crittografico sicuro e lo memorizza all'interno della stringa hash restituita, il che significa che non è necessaria una colonna di database separata per i salt.

---

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

PHP 5.5 introduce due strumenti estremamente pratici:

### 1. `array_column()`
Estrae una singola colonna da un array multidimensionale o da un gruppo di oggetti.

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

### 2. `ClassName::class`
Restituisce il nome completo con namespace di una classe sotto forma di stringa.

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

---

<a id="opcache"></a>
## Integrazione di Zend OPcache

Zend OPcache è ora parte integrante del core di PHP. Memorizza in memoria il bytecode PHP compilato, in modo che i file non debbano essere analizzati e compilati ad ogni richiesta.

* **Perché è importante**: Aumenta le prestazioni di produzione da 2 a 3 volte a seconda delle dimensioni del framework utilizzato.
* **Conseguenza**: Gli sviluppatori devono implementare strategie di pulizia della cache (come chiamare `opcache_reset()` o riavviare il gestore dei processi PHP-FPM) durante le procedure di deploy.

---

<a id="common-mistakes"></a>
## ⚠️ Errori comuni

### 1. Utilizzo del pericoloso modificatore `/e` in `preg_replace`
Il modificatore `/e` valuta la stringa di sostituzione come codice PHP, portando a vulnerabilità di Remote Code Execution (RCE). È deprecato in PHP 5.5.

```php
// app/Helpers/StringHelper.php
// ❌ Deprecato e altamente insicuro!
$output = preg_replace('/(\w+)/e', 'strtoupper("$1")', $text);

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

### 2. Mancata pulizia delle risorse dei generatori in caso di uscita prematura dal ciclo
Se esci prematuramente da un ciclo di un generatore (break), le risorse come i file aperti possono rimanere aperte a meno che non siano racchiuse in blocchi `try/finally` all'interno del generatore stesso.

```php
// app/Services/FileReader.php
// ❌ Pericoloso: se il ciclo si interrompe, fclose() non viene mai eseguito
function readData($file) {
    $fh = fopen($file, 'r');
    while($line = fgets($fh)) yield $line;
    fclose($fh);
}

// ✅ Approccio corretto
function readDataSafe($file) {
    $fh = fopen($file, 'r');
    try {
        while($line = fgets($fh)) yield $line;
    } finally {
        fclose($fh); // Esecuzione garantita quando il generatore viene distrutto
    }
}
```

### 3. Affidarsi alla vecchia estensione `mysql`
Le funzioni `mysql_connect()` sono deprecate in PHP 5.5.

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

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

---

<a id="practical-recipes"></a>
## Ricette pratiche

### Aspettative vs Realtà: `finally` e istruzioni Return

Cosa succede quando sia il blocco `try` che il blocco `finally` restituiscono un valore?

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

// Aspettativa: Restituisce "Ritorno da try"
// Realtà:
echo testFinally(); // Output: Ritorno da finally
```

> [!WARNING]
> Se si restituisce un valore all'interno del blocco `finally`, questo sovrascriverà qualsiasi valore restituito nei blocchi `try` o `catch`. Evitare di inserire istruzioni `return` all'interno di `finally`.

---

<a id="backward-incompatible"></a>
## Modifiche non retrocompatibili

1. **Deprecazione del modificatore `/e` in `preg_replace`**: Genera avvisi; è necessario utilizzare `preg_replace_callback()`.
2. **Deprecazione dell'estensione `mysql`**: Genera avvisi `E_DEPRECATED` al momento della connessione.
3. **`empty()` applicato alle espressioni**: Prima di PHP 5.5, `empty()` accettava solo variabili (es. `empty($x)`). Ora accetta espressioni come `empty(trim($x))`. Sebbene non sia un break diretto, rende obsoleti i vecchi workaround.
4. **Modifiche al formato di `pack()` e `unpack()`**: Alcune modifiche all'allineamento a 64 bit potrebbero influire sulla serializzazione binaria.

---

## 🧠 Domande di autovalutazione

1. **Vero o Falso?** Una funzione generatore restituisce un oggetto `Generator` che implementa l'interfaccia `Iterator`.
2. Se viene generata un'eccezione in un blocco `try` e NON viene catturata da alcun blocco `catch`, il codice all'interno del blocco `finally` viene comunque eseguito?
3. Cosa succede se si tenta di passare direttamente un array di parametri di costo a `password_verify()`?
4. **Vero o Falso?** `ClassName::class` funziona a runtime anche se la classe non è caricata o non esiste.

<details>
<summary><b>Mostra risposte</b></summary>

1. **Vero.** I generatori restituiscono un'istanza della classe `Generator`, il che consente di utilizzarli direttamente all'interno dei cicli `foreach`.
2. **Sì.** L'esecuzione del blocco `finally` è garantita prima che l'eccezione si propaghi verso l'alto e interrompa l'esecuzione dello script.
3. Nulla, perché `password_verify` accetta solo due argomenti: la password in chiaro e l'hash. Legge l'algoritmo e i parametri di costo direttamente dalla stringa hash stessa.
4. **Vero.** `::class` viene risolto a tempo di compilazione. Non tenta l'autoloading né verifica l'esistenza della classe; restituisce semplicemente la stringa del namespace.
</details>