# Il php.ini spiegato: struttura, livelli e precedenza

> Il php.ini spiegato: dove PHP cerca la configurazione, quali livelli esistono, che cosa significano INI_SYSTEM e INI_PERDIR e quale valore vale alla fine.

Fonte: https://phpsos.de/it/php/php-ini-erklaert/  
Stato: 25/10/2026  
Fornitore: PHP SOS, Assistenza di emergenza PHP e sicurezza dei server. Assistenza immediata su WhatsApp: https://wa.me/491736494914?text=Buongiorno%20PHP%20SOS%2C%20abbiamo%20bisogno%20di%20aiuto%20con%20il%20nostro%20server%20PHP.%20Azienda%3A%20%E2%80%A6%20Sito%20web%3A%20%E2%80%A6

**In breve:** il php.ini è il file di configurazione centrale di PHP. PHP lo legge all'avvio, con i moduli del server una volta, con CGI e CLI a ogni chiamata. A questo si aggiungono file supplementari da una directory di scansione, impostazioni nel pool FPM o in Apache, `.htaccess` o `.user.ini` e `ini_set()` nel codice. Quale livello possa modificare un valore lo stabilisce la sua modalità di modifica, ad esempio `INI_SYSTEM` o `INI_PERDIR`. I valori impostati con `php_admin_value` l'applicazione non può più sovrascriverli.

## Che cos'è il php.ini?

Il php.ini è un file di testo con voci secondo lo schema `name = wert`. Stabilisce come si comporta PHP: quanta memoria può usare uno script, se gli errori compaiono nel browser, come lavorano le sessioni e quali estensioni vengono caricate. I commenti iniziano con un punto e virgola.

Secondo il manuale PHP il file viene letto all'avvio di PHP. Con i moduli del server come mod_php ciò avviene una sola volta, all'avvio del server web, con CGI e CLI a ogni chiamata. PHP-FPM legge la sua configurazione all'avvio e al ricaricamento del servizio. Una modifica senza riavvio o reload perciò di solito non ha effetto.

Da PHP 8.3, secondo il manuale, una voce può rimandare a una variabile d'ambiente con un valore sostitutivo:

```ini
memory_limit = ${PHP_MEMORY_LIMIT}
max_execution_time = ${PHP_MAX_EXECUTION_TIME:-30}
```

## Dove cerca PHP il php.ini?

Il manuale descrive un ordine fisso. Per prima vale un percorso impostato espressamente, ad esempio `PHPIniDir` in Apache o l'opzione `-c` con CGI e CLI. Altrimenti PHP costruisce un percorso di ricerca da:

1. la variabile d'ambiente `PHPRC`,
2. su Windows la voce di registro `IniFilePath`,
3. la directory di lavoro corrente, tranne che per le SAPI che lo disattivano, ad esempio la CLI,
4. la directory del binario PHP o del modulo,
5. il percorso impostato in compilazione `--with-config-file-path`.

In questo percorso di ricerca PHP cerca prima un file `php-SAPI.ini`, ad esempio `php-cli.ini`, e solo dopo `php.ini`. Poi PHP legge in ordine alfabetico tutti i file `.ini` della directory di scansione, definita tramite `PHP_INI_SCAN_DIR` o, in compilazione, tramite `--with-config-file-scan-dir`. Quali file siano stati caricati lo mostrano `php --ini` o la funzione `php_ini_scanned_files()`.

```bash
php --ini
php -r 'var_dump(php_ini_loaded_file(), php_ini_scanned_files());'
```

Entrambi i comandi mostrano lo stato della riga di comando. Per il sito web può valere un altro file, perché ogni SAPI può avere la propria configurazione; maggiori dettagli in [SAPI spiegata](https://phpsos.de/it/php/sapi-erklaert/).

## Modalità di modifica: chi può impostare quale valore?

Non ogni impostazione può essere definita ovunque. Il manuale assegna a ogni direttiva una modalità di modifica:

| Modalità | Dove si può impostare il valore |
|---|---|
| `INI_USER` | negli script con `ini_set()`, nel registro di Windows e in `.user.ini` |
| `INI_PERDIR` | in php.ini, `.htaccess`, `httpd.conf` o `.user.ini` |
| `INI_SYSTEM` | solo in php.ini o `httpd.conf` |
| `INI_ALL` | ovunque |

Esempi dal manuale: `memory_limit` ha la modalità `INI_ALL` e il valore predefinito `128M`, `post_max_size` ha `INI_PERDIR` e il valore predefinito `8M`, `upload_max_filesize` ha `INI_PERDIR` e il valore predefinito `2M`. `expose_php` può stare solo nel php.ini.

I file `.user.ini`, secondo il manuale, vengono letti solo dalle SAPI CGI e FastCGI, quindi anche da PHP-FPM. PHP li cerca dalla directory dello script verso l'alto fino al document root e li rilegge per impostazione predefinita al massimo ogni 300 secondi (`user_ini.cache_ttl`). Con mod_php questo ruolo è svolto da `.htaccess`.

## Quale valore vale alla fine? I livelli in ordine di precedenza

In modo semplificato: più tardi interviene un livello, più facilmente il suo valore prevale, purché la modalità di modifica lo consenta.

1. **php.ini** della rispettiva SAPI
2. **File supplementari** dalla directory di scansione, in ordine alfabetico
3. **Configurazione del server:** pool FPM con `php_value` o `php_admin_value`, VirtualHost di Apache
4. **Livello di directory:** `.htaccess` con mod_php, `.user.ini` con FPM e CGI
5. **Runtime:** `ini_set()` nel codice dell'applicazione

L'eccezione è decisiva: i valori impostati con `php_admin_value` o `php_admin_flag` non possono, secondo il manuale, essere sovrascritti con `ini_set()`. Così gli amministratori bloccano le impostazioni rilevanti per la sicurezza contro l'applicazione. La descrizione dettagliata è in [php_admin_value: bloccare le impostazioni contro la sovrascrittura](https://phpsos.de/it/blog/php-admin-value-sperren/).

## Il php.ini dopo PHP2Shell: che cosa è cambiato

Le misure transitorie di php.net contro PHP2Shell sono quasi tutte impostazioni INI: `memory_limit=-1` bloccato contro la sovrascrittura, `post_max_size` limitato, `session.upload_progress.enabled=0` e, su PHP 8.5, `fatal_error_backtraces=0`. php.net sottolinea che `session.upload_progress.enabled` non deve essere impostato tramite `ini_set()` o `.user.ini`, ma in php.ini, nel pool FPM o nella configurazione del server, con successivo riavvio di tutti i worker. L'elenco completo è in [Misure immediate se non potete ancora aggiornare](https://phpsos.de/it/php2shell/sofortmassnahmen-ohne-patch/).

Con le versioni corrette 8.5.12, 8.4.27, 8.3.36 e 8.2.35 è cambiato, secondo il manuale, anche `memory_limit`: ora è un limite morbido. La nuova impostazione `memory_hard_limit_percent` stabilisce un limite rigido. Senza valore proprio è il doppio di `memory_limit`, per valori superiori a `1G` il valore più `1G`. Se viene superato, il processo termina subito con stato di uscita 137. Come scegliere in modo sensato i due limiti lo spiega [Impostare correttamente memory_limit](https://phpsos.de/it/blog/memory-limit-richtig-setzen/).

> **Consiglio:**
> Secondo il manuale vale: se una versione di PHP non riconosce `memory_hard_limit_percent`, è interessata da CVE-2026-109618 e CVE-2026-109619. Per le distribuzioni con backport lo stato lo documenta inoltre il changelog del pacchetto.

## Come aiuta concretamente PHP SOS?

- **Accertare i valori effettivi:** leggiamo per ogni SAPI quali file vengono caricati e quale valore vale alla fine.
- **Riordinare i livelli:** rimuoviamo le voci contraddittorie da pannelli, pool, `.htaccess` e `.user.ini`.
- **Impostare i blocchi:** nell'ambito dell'[hardening del server](https://phpsos.de/it/leistungen/server-haertung/) fissiamo i valori rilevanti per la sicurezza con `php_admin_value`.
- **Documentare:** registriamo impostazioni e riavvio, perché lo stato sia in seguito dimostrabile.


## Domande frequenti

**Dov'è il php.ini?**  
Dipende da sistema operativo, pacchetto e SAPI. Su Debian e Ubuntu esistono cartelle proprie per ogni versione e SAPI, ad esempio /etc/php/8.3/fpm/php.ini e /etc/php/8.3/cli/php.ini. Da riga di comando php --ini mostra i file caricati, per il sito web aiuta php_ini_loaded_file() in un file di verifica temporaneo.

**In che ordine vengono letti i file nella cartella conf.d?**  
Secondo il manuale PHP, PHP legge in ordine alfabetico tutti i file con estensione .ini nella directory di scansione. I file successivi sovrascrivono i valori di quelli precedenti. Per questo molti file hanno nel nome numeri come 20- o 99-.

**Perché la mia modifica al php.ini non ha effetto?**  
Motivi frequenti: è stato modificato il file di un'altra SAPI, il servizio non è stato riavviato, un valore nel pool FPM, nella configurazione di Apache o in un .user.ini lo sovrascrive, oppure un pannello di hosting riscrive il file al salvataggio successivo.

**Che cos'è memory_hard_limit_percent?**  
Una nuova impostazione introdotta, secondo il manuale PHP, con le release di sicurezza del 21/10/2026. Stabilisce un limite di memoria rigido come percentuale di memory_limit. Il manuale avverte che una versione di PHP che non conosce questa impostazione è interessata dalle vulnerabilità di PHP2Shell.

## Fonti

- [Manuale PHP: il file di configurazione](https://www.php.net/manual/en/configuration.file.php)
- [Manuale PHP: modalità di modifica INI](https://www.php.net/manual/en/configuration.changes.modes.php)
- [Manuale PHP: file .user.ini](https://www.php.net/manual/en/configuration.file.per-user.php)
- [Manuale PHP: impostazioni del core](https://www.php.net/manual/en/ini.core.php)
