Easy📖Теория5 min

Основы php.ini

Как PHP читает конфигурацию, php.ini-development vs php.ini-production, phpinfo(), ini_get/ini_set, .user.ini, уровни директив

Основы php.ini

Что такое php.ini

php.ini -- главный конфигурационный файл PHP. Он читается один раз при старте интерпретатора (запуск PHP-FPM, Apache или CLI) и определяет поведение всего движка.

Порядок поиска конфигурации

PHP ищет php.ini в определённой последовательности:

  1. Переменная окружения PHPRC (если задана)
  2. Путь, специфичный для SAPI (например, /etc/php/8.4/fpm/)
  3. Путь, указанный при компиляции (--with-config-file-path)
  4. Текущая рабочая директория (только CLI)
  5. Директория сервера (для SAPI-модулей)
  6. Системные директории (/etc/ на Linux)
<?php

// Find where PHP looks for configuration
echo php_ini_loaded_file();
// Example: /etc/php/8.4/fpm/php.ini

echo php_ini_scanned_files();
// /etc/php/8.4/fpm/conf.d/10-opcache.ini,
// /etc/php/8.4/fpm/conf.d/20-curl.ini, ...

Стандартные пути для разных SAPI

Linux (FPM):    /etc/php/8.4/fpm/php.ini
Linux (CLI):    /etc/php/8.4/cli/php.ini
macOS (brew):   /opt/homebrew/etc/php/8.4/php.ini
Docker:         /usr/local/etc/php/php.ini
Windows:        C:\php\php.ini

Критически важно: CLI и FPM используют разные файлы php.ini. Изменение настроек в одном не влияет на другой. Это частая причина "у меня в терминале работает, а на сайте нет".


php.ini-development vs php.ini-production

PHP поставляется с двумя шаблонами конфигурации. Ни один из них не является активным по умолчанию -- нужно скопировать выбранный в php.ini.

Директива development production Почему
display_errors On Off Безопасность: не показывать ошибки пользователю
display_startup_errors On Off Ошибки при старте PHP
error_reporting E_ALL E_ALL Логировать все уровни
log_errors On On Всегда писать логи
error_log (пусто) (пусто) Настроить путь вручную!
opcache.enable 0 1 Кеширование для производительности
zend.exception_ignore_args Off On Не хранить аргументы в stack trace
zend.exception_string_param_max_len 15 0 Не показывать параметры
mysqlnd.collect_memory_statistics On Off Сбор статистики замедляет
# Setting up configuration from template
cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini

# In Docker
COPY --from=build /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini

phpinfo() -- полная справка

<?php

// Full information (NEVER leave on production!)
phpinfo();

// Specific sections using constants
phpinfo(INFO_GENERAL);       // PHP version, build date, SAPI
phpinfo(INFO_CONFIGURATION); // php.ini directives and values
phpinfo(INFO_MODULES);       // Loaded extensions and settings
phpinfo(INFO_ENVIRONMENT);   // Environment variables
phpinfo(INFO_VARIABLES);     // $_SERVER, $_ENV, $_GET, etc.

// Section flags can be combined with bitwise OR
phpinfo(INFO_GENERAL | INFO_CONFIGURATION);

CLI-альтернативы

# Quick directive lookup
php -i | grep memory_limit

# Get specific value
php -r "echo ini_get('memory_limit');"

# List all loaded ini files
php --ini

# Show compiled-in configuration path
php -i | grep "Configuration File"

Безопасность: phpinfo() раскрывает версии ПО, пути файловой системы, переменные окружения и расширения. На production это прямой вектор атаки.


ini_get() и ini_set()

Чтение значений

<?php

// ini_get() always returns string (or false if directive doesn't exist)
$memLimit = ini_get('memory_limit');       // "128M"
$maxExec = ini_get('max_execution_time');  // "30"
$display = ini_get('display_errors');      // "0" or "1"

// WARNING: boolean directives return "0", "1", "" or "Off", "On"
var_dump(ini_get('display_errors')); // string("0")

// Correct boolean check
$isEnabled = filter_var(
    ini_get('display_errors'),
    FILTER_VALIDATE_BOOLEAN
);

// ini_get_all() -- all directives with access levels
$all = ini_get_all();
// ['directive' => ['global_value' => '...', 'local_value' => '...', 'access' => 7]]

// Directives for specific extension
$opcache = ini_get_all('opcache');

Изменение значений

<?php

// ini_set() changes value for CURRENT SCRIPT only
$oldValue = ini_set('memory_limit', '256M');
echo "Was: $oldValue, Now: " . ini_get('memory_limit');

// Restore original value from php.ini
ini_restore('memory_limit');
echo ini_get('memory_limit'); // Back to php.ini value

// ini_set() returns false on failure (directive doesn't exist or wrong level)
$result = ini_set('upload_max_filesize', '100M'); // false! (PHP_INI_PERDIR)

Уровни конфигурации (INI Access Levels)

Каждая директива PHP имеет уровень доступа, определяющий, где её можно изменить.

Уровень Значение Где можно изменить
PHP_INI_USER 1 ini_set(), .user.ini
PHP_INI_PERDIR 2 .user.ini, .htaccess, httpd.conf
PHP_INI_SYSTEM 4 Только php.ini, httpd.conf
PHP_INI_ALL 7 Все способы (1+2+4)
<?php

// Check access level of any directive
$info = ini_get_all();

echo $info['memory_limit']['access'];        // 7 (PHP_INI_ALL)
echo $info['upload_max_filesize']['access'];  // 6 (PERDIR + SYSTEM)
echo $info['max_file_uploads']['access'];     // 4 (PHP_INI_SYSTEM)
echo $info['error_reporting']['access'];      // 7 (PHP_INI_ALL)

Практические следствия

<?php

// PHP_INI_ALL -- can change anywhere
ini_set('memory_limit', '512M');          // Works
ini_set('error_reporting', (string) E_ALL); // Works
ini_set('max_execution_time', '60');      // Works

// PHP_INI_PERDIR -- only php.ini, .user.ini, httpd.conf
ini_set('upload_max_filesize', '100M');   // SILENTLY IGNORED!
ini_set('session.save_handler', 'redis'); // SILENTLY IGNORED!

// PHP_INI_SYSTEM -- only php.ini and httpd.conf
ini_set('disable_functions', 'exec');     // SILENTLY IGNORED!
ini_set('open_basedir', '/var/www');      // SILENTLY IGNORED!

Для экзамена: ini_set() для директивы с неподходящим уровнем не вызывает ошибку -- вызов просто игнорируется и возвращает false.


.user.ini -- пользовательская конфигурация

.user.ini -- аналог .htaccess для PHP-FPM (и FastCGI). Размещается в любой директории проекта и влияет на файлы в ней и поддиректориях.

; /var/www/project/.user.ini

; PHP_INI_ALL and PHP_INI_PERDIR directives work here
memory_limit = 256M
upload_max_filesize = 50M
post_max_size = 55M
max_execution_time = 60

; PHP_INI_SYSTEM directives DO NOT work here!
; disable_functions = exec     ; This line has no effect
; max_file_uploads = 100       ; This line has no effect

Кеширование .user.ini

; Controlled by these php.ini directives:
user_ini.filename = ".user.ini"    ; File name (can be changed)
user_ini.cache_ttl = 300           ; Cache TTL in seconds (default 5 min)

Важно: После изменения .user.ini нужно подождать до user_ini.cache_ttl секунд или перезапустить PHP-FPM. .user.ini работает только с PHP-FPM и FastCGI. С Apache mod_php используется .htaccess с php_value/php_flag.


Приоритет применения настроек

php.ini             (самый низкий приоритет)
    |
conf.d/*.ini        (дополнительные файлы, в алфавитном порядке)
    |
.user.ini           (пользовательская конфигурация)
    |
ini_set()           (самый высокий, только PHP_INI_ALL/PHP_INI_USER)
<?php

// php.ini: memory_limit = 128M
// .user.ini: memory_limit = 256M
// Script:
ini_set('memory_limit', '512M');
echo ini_get('memory_limit'); // "512M" -- ini_set() wins

ini_restore('memory_limit');
echo ini_get('memory_limit'); // "256M" -- .user.ini value (FPM)

// Check both values
$info = ini_get_all(null, true)['memory_limit'];
echo $info['global_value']; // "128M" (from php.ini)
echo $info['local_value'];  // "512M" (current effective)

Формат значений в php.ini

; Strings
error_log = /var/log/php/error.log

; Numbers
max_execution_time = 30

; Sizes with suffixes: K (kilobytes), M (megabytes), G (gigabytes)
memory_limit = 128M
post_max_size = 64M

; Boolean values (all equivalent)
display_errors = On     ; On, Off, 1, 0, true, false, yes, no

; Lists (comma-separated)
disable_functions = exec,shell_exec,system,passthru,proc_open

; Empty value (disable/unset)
error_log =

; Comments
; This is a comment (semicolons only)

Частая ошибка: memory_limit = 128 (без суффикса) означает 128 байт, а не 128 мегабайт!


Конфигурация через переменные окружения (Docker)

; In Docker, override directives via environment variables
; PHP_INI_SCAN_DIR controls additional .ini directories

; /usr/local/etc/php/conf.d/docker.ini
; Use envsubst or sed in entrypoint:
memory_limit = ${PHP_MEMORY_LIMIT:-128M}
# Docker entrypoint approach
envsubst < /usr/local/etc/php/conf.d/docker.ini.template \
         > /usr/local/etc/php/conf.d/docker.ini

# Or override with -d flag
php -d memory_limit=256M script.php

Проверь себя

🧪

Что произойдёт при вызове `ini_set('disable_functions', 'exec')`?

🧪

Что вернёт `ini_get('display_errors')` если директива выключена?

🧪

В каком порядке PHP загружает файлы из conf.d/?

🧪

Где `.user.ini` НЕ работает?

🧪

Какой уровень доступа имеет директива `upload_max_filesize`?