# El php.ini explicado: estructura, niveles y prioridad

> El php.ini explicado: dónde busca PHP su configuración, qué niveles existen, qué significan INI_SYSTEM e INI_PERDIR y qué valor se aplica al final.

Fuente: https://phpsos.de/es/php/php-ini-erklaert/  
Actualizado: 25/10/2026  
Proveedor: PHP SOS, Ayuda de emergencia para PHP y seguridad de servidores. Ayuda inmediata por WhatsApp: https://wa.me/491736494914?text=Hola%20PHP%20SOS%2C%20necesitamos%20ayuda%20con%20nuestro%20servidor%20PHP.%20Empresa%3A%20%E2%80%A6%20Sitio%20web%3A%20%E2%80%A6

**En resumen:** el php.ini es el archivo de configuración central de PHP. PHP lo lee al iniciar: una vez en los módulos de servidor y en cada invocación en CGI y CLI. A ello se suman archivos adicionales de un directorio de escaneo, ajustes en el pool de FPM o en Apache, `.htaccess` o `.user.ini`, y `ini_set()` en el código. Qué nivel puede modificar un valor lo determina su modo de modificación, por ejemplo `INI_SYSTEM` o `INI_PERDIR`. Los valores fijados con `php_admin_value` ya no puede sobrescribirlos la aplicación.

## ¿Qué es el php.ini?

El php.ini es un archivo de texto con entradas del tipo `name = wert`. Determina cómo se comporta PHP: cuánta memoria puede usar un script, si los errores aparecen en el navegador, cómo funcionan las sesiones y qué extensiones se cargan. Los comentarios empiezan con un punto y coma.

Según el manual de PHP, el archivo se lee al iniciar PHP. En los módulos de servidor como mod_php esto ocurre solo una vez, al iniciar el servidor web; en CGI y CLI, en cada invocación. PHP-FPM lee su configuración al iniciar y al recargar el servicio. Por eso, un cambio sin reinicio o recarga normalmente no surte efecto.

Desde PHP 8.3, según el manual, una entrada puede remitir a una variable de entorno con un valor de sustitución:

```ini
memory_limit = ${PHP_MEMORY_LIMIT}
max_execution_time = ${PHP_MAX_EXECUTION_TIME:-30}
```

## ¿Dónde busca PHP el php.ini?

El manual describe un orden fijo. Primero cuenta una ruta fijada expresamente, por ejemplo `PHPIniDir` en Apache o la opción `-c` en CGI y CLI. Si no, PHP construye una ruta de búsqueda con:

1. la variable de entorno `PHPRC`,
2. en Windows, la entrada del registro `IniFilePath`,
3. el directorio de trabajo actual, salvo en las SAPI que lo desactivan, como la CLI,
4. el directorio del binario de PHP o del módulo,
5. la ruta fijada al compilar con `--with-config-file-path`.

En esta ruta de búsqueda, PHP busca primero un archivo `php-SAPI.ini`, por ejemplo `php-cli.ini`, y solo después `php.ini`. A continuación, PHP lee en orden alfabético todos los archivos `.ini` del directorio de escaneo, fijado mediante `PHP_INI_SCAN_DIR` o, al compilar, mediante `--with-config-file-scan-dir`. Qué archivos se han cargado lo muestran `php --ini` o la función `php_ini_scanned_files()`.

```bash
php --ini
php -r 'var_dump(php_ini_loaded_file(), php_ini_scanned_files());'
```

Ambos comandos muestran el estado de la línea de comandos. Para el sitio web puede aplicarse otro archivo, porque cada SAPI puede tener su propia configuración; más información en [SAPI explicada](https://phpsos.de/es/php/sapi-erklaert/).

## Modos de modificación: ¿quién puede fijar qué valor?

No todo ajuste puede fijarse en cualquier lugar. El manual asigna a cada directiva un modo de modificación:

| Modo | Dónde puede fijarse el valor |
|---|---|
| `INI_USER` | en scripts con `ini_set()`, en el registro de Windows y en `.user.ini` |
| `INI_PERDIR` | en php.ini, `.htaccess`, `httpd.conf` o `.user.ini` |
| `INI_SYSTEM` | solo en php.ini o `httpd.conf` |
| `INI_ALL` | en cualquier lugar |

Ejemplos del manual: `memory_limit` tiene el modo `INI_ALL` y el valor por defecto `128M`; `post_max_size` tiene `INI_PERDIR` y el valor por defecto `8M`; `upload_max_filesize` tiene `INI_PERDIR` y el valor por defecto `2M`. `expose_php` solo puede figurar en el php.ini.

Según el manual, los archivos `.user.ini` solo los leen las SAPI de CGI y FastCGI, es decir, también PHP-FPM. PHP los busca desde el directorio del script hacia arriba hasta el Document Root y, por defecto, los vuelve a leer como máximo cada 300 segundos (`user_ini.cache_ttl`). En mod_php, `.htaccess` asume este papel.

## ¿Qué valor se aplica al final? Los niveles por prioridad

De forma simplificada: cuanto más tarde actúa un nivel, más probable es que su valor prevalezca, siempre que el modo de modificación lo permita.

1. **php.ini** de la SAPI correspondiente
2. **Archivos adicionales** del directorio de escaneo, en orden alfabético
3. **Configuración del servidor:** pool de FPM con `php_value` o `php_admin_value`, VirtualHost de Apache
4. **Nivel de directorio:** `.htaccess` en mod_php, `.user.ini` en FPM y CGI
5. **Tiempo de ejecución:** `ini_set()` en el código de la aplicación

La excepción es decisiva: según el manual, los valores fijados con `php_admin_value` o `php_admin_flag` no pueden sobrescribirse con `ini_set()`. Así, los administradores bloquean frente a la aplicación los ajustes relevantes para la seguridad. Se describe con detalle en [php_admin_value: bloquear ajustes frente a la sobrescritura](https://phpsos.de/es/blog/php-admin-value-sperren/).

## El php.ini tras PHP2Shell: qué ha cambiado

Las medidas provisionales de php.net frente a PHP2Shell son casi todas ajustes INI: `memory_limit=-1` bloqueado frente a la sobrescritura, `post_max_size` limitado, `session.upload_progress.enabled=0` y, en PHP 8.5, `fatal_error_backtraces=0`. php.net subraya que `session.upload_progress.enabled` no debe fijarse mediante `ini_set()` ni `.user.ini`, sino en php.ini, en el pool de FPM o en la configuración del servidor, con el posterior reinicio de todos los workers. La lista completa está en [Medidas inmediatas si aún no puede parchear](https://phpsos.de/es/php2shell/sofortmassnahmen-ohne-patch/).

Con las versiones corregidas 8.5.12, 8.4.27, 8.3.36 y 8.2.35, según el manual, también ha cambiado `memory_limit`: ahora es un límite blando. El nuevo ajuste `memory_hard_limit_percent` fija un límite duro. Sin un valor propio equivale al doble de `memory_limit` y, si supera `1G`, al valor más `1G`. Si se supera, el proceso termina de inmediato con estado de salida 137. Cómo elegir ambos límites de forma razonable lo explica [Fijar memory_limit correctamente](https://phpsos.de/es/blog/memory-limit-richtig-setzen/).

> **Consejo:**
> Según el manual: si una versión de PHP no reconoce `memory_hard_limit_percent`, está afectada por CVE-2026-109618 y CVE-2026-109619. En las distribuciones con backports, el changelog del paquete demuestra además el estado.

## ¿Cómo ayuda PHP SOS en concreto?

- **Averiguar los valores efectivos:** leemos para cada SAPI qué archivos se cargan y qué valor se aplica al final.
- **Ordenar los niveles:** eliminamos entradas contradictorias de paneles, pools, `.htaccess` y `.user.ini`.
- **Establecer bloqueos:** en el marco del [refuerzo del servidor](https://phpsos.de/es/leistungen/server-haertung/) fijamos mediante `php_admin_value` los valores relevantes para la seguridad.
- **Documentar:** documentamos los ajustes y el reinicio para que el estado pueda demostrarse más adelante.


## Preguntas frecuentes

**¿Dónde está el php.ini?**  
Depende del sistema operativo, del paquete y de la SAPI. En Debian y Ubuntu hay carpetas propias para cada versión y SAPI, por ejemplo /etc/php/8.3/fpm/php.ini y /etc/php/8.3/cli/php.ini. En la línea de comandos, php --ini muestra los archivos cargados; para el sitio web ayuda php_ini_loaded_file() en un archivo de prueba colocado de forma breve.

**¿En qué orden se leen los archivos de la carpeta conf.d?**  
Según el manual de PHP, PHP lee todos los archivos con la extensión .ini del directorio de escaneo en orden alfabético. Los archivos posteriores sobrescriben los valores de los anteriores. Por eso muchos archivos llevan números como 20- o 99- en el nombre.

**¿Por qué no surte efecto mi cambio en el php.ini?**  
Motivos frecuentes: se modificó el archivo de otra SAPI, no se reinició el servicio, un valor en el pool de FPM, en la configuración de Apache o en un .user.ini lo sobrescribe, o un panel de hosting vuelve a escribir el archivo la próxima vez que se guarda.

**¿Qué es memory_hard_limit_percent?**  
Un ajuste nuevo que, según el manual de PHP, se introdujo con las versiones de seguridad del 21/10/2026. Fija un límite de memoria duro como porcentaje de memory_limit. El manual advierte de que una versión de PHP que no conozca este ajuste está afectada por las vulnerabilidades de PHP2Shell.

## Fuentes

- [Manual de PHP: el archivo de configuración](https://www.php.net/manual/en/configuration.file.php)
- [Manual de PHP: modos de modificación de INI](https://www.php.net/manual/en/configuration.changes.modes.php)
- [Manual de PHP: archivos .user.ini](https://www.php.net/manual/en/configuration.file.per-user.php)
- [Manual de PHP: ajustes del núcleo](https://www.php.net/manual/en/ini.core.php)
