Конфигурация PHP: от глобального файла до точечных настроек
Файл php.ini является основным файлом конфигурации интерпретатора PHP. Он управляет такими параметрами, как ограничение памяти, время выполнения скриптов, размер загружаемых файлов, настройки сессий, включение расширений и многие другие. Расположение файла зависит от операционной системы и способа установки. Для веб-сервера обычно используется один глобальный php.ini, но существуют способы задать индивидуальные настройки для отдельных каталогов или скриптов. В этой статье рассматриваются различные подходы к изменению конфигурации PHP.
Основные методы управления настройками PHP
Как изменить глобальные параметры PHP через основной php.ini?
Наиболее эффективным и централизованным решением является редактирование главного конфигурационного файла php.ini, который загружается при старте PHP (например, при запуске веб-сервера или php-fpm). После внесения изменений требуется перезагрузка веб-сервера или php-fpm для применения.
Пример: увеличение лимита памяти до 256 МБ и максимального времени выполнения до 120 секунд.
memory_limit = 256M
max_execution_time = 120файл настройки php (файл настроек php)
После редактирования файла необходимо перезапустить службу:
# Для Apache с mod_php
sudo systemctl restart apache2
# Для PHP-FPM
sudo systemctl restart php8.1-fpm
Цель: обеспечить единую конфигурацию для всех скриптов на сервере. Подходит для серверов с одним приложением или когда все сайты нуждаются в одинаковых настройках.
Типичные проблемы:
- Файл php.ini может быть защищён от записи. Необходимо проверить права доступа.
- Неверное значение директивы (например, memory_limit = -1 для бесконечной памяти) может привести к уязвимости или нестабильной работе.
- После изменения некоторых директив (особенно касающихся ресурсов) может потребоваться увеличение ulimit или настройка системных лимитов.
- Если используется несколько версий PHP, нужно редактировать php.ini для каждой версии отдельно.
Как задать настройки PHP для конкретной директории через .user.ini?
При использовании PHP-FPM (или CGI/FastCGI) поддерживаются файлы .user.ini, которые действуют аналогично php.ini, но на уровне каталога. Они позволяют изменить директивы без влияния на другие сайты.
Случаи использования: хостинг с несколькими сайтами, где нет доступа к глобальному php.ini, или требуется специфическая конфигурация для отдельного приложения (например, увеличенный размер загрузки для файлового менеджера).
Пример: в корне сайта создать файл .user.ini со следующим содержимым:
upload_max_filesize = 50M
post_max_size = 60M
max_execution_time = 300
Файл загружается автоматически при старте PHP для запросов, корень которых находится в данной директории или её поддиректориях.
Ошибки и их решение:
- Директивы .user.ini могут быть переопределены глобальными настройками, если они имеют более высокий приоритет. Необходимо убедиться, что сервер разрешает переопределение (директива user_ini.filename включена).
- Не все директивы можно менять через .user.ini (например, ограничения ресурсов ядра PHP). Список директив, доступных в .user.ini, описан в документации PHP.
- Изменения в .user.ini вступают в силу без перезагрузки сервера, но может потребоваться очистка кэша opcache.
Как изменить настройки PHP прямо в скрипте с помощью ini_set()?
Функция ini_set() позволяет изменить значение директивы PHP во время выполнения скрипта. Это удобно для временных изменений внутри конкретного приложения.
Цель: динамически адаптировать поведение PHP под конкретный запрос, например, увеличить время выполнения при генерации отчёта.
Пример:
<?php
ini_set('memory_limit', '512M');
ini_set('max_execution_time', '0'); // без ограничения
// код, требующий много ресурсов
?>
Результат будет действовать только на текущий скрипт и его вызовы (включая включённые файлы). После завершения выполнения возвращаются прежние значения.
Возможные сложности:
- Некоторые директивы нельзя изменить таким способом (например, register_globals, safe_mode, которые являются устаревшими). Их можно узнать в документации по PHP_INI_* режимам.
- Если скрипт использует opcache, изменения через ini_set() не влияют на кэшированный код, и опкод может остаться со старыми настройками. В таких случаях поможет очистка кэша.
- Вызов ini_set() может быть запрещён в некоторых окружениях (например, в restricted режимах).
Как настроить PHP через .htaccess при использовании mod_php в Apache?
Если PHP работает как модуль Apache (mod_php), директивы можно задать в файле .htaccess с помощью директивы php_value или php_flag. Это позволяет изменять настройки для отдельных каталогов без доступа к основному конфигу.
Пример:
php_value upload_max_filesize 100M
php_value post_max_size 105M
php_flag display_errors on
Такие настройки распространяются на текущий и все вложенные каталоги (если они не переопределены в подкаталогах).
Проблемы:
- Данный метод работает только с mod_php; для PHP-FPM или CGI необходимо использовать другие способы.
- Для использования php_value в .htaccess требуется опция
AllowOverride OptionsилиAllowOverride Allв конфигурации виртуального хоста. - Синтаксис php_value не поддерживает значения с пробелами, если они не заключены в кавычки.
Как применить разные настройки PHP для разных сайтов при использовании PHP-FPM?
В PHP-FPM можно создавать отдельные пулы (pool), каждый со своим конфигурационным файлом в каталоге pool.d. Внутри файла пула можно задать директивы через php_value, php_flag или php_admin_value.
Цель: изоляция ресурсов между несколькими приложениями на одном сервере (например, ограничение памяти для каждого сайта).
Пример конфигурации пула (например, /etc/php/8.1/fpm/pool.d/site1.conf):
[site1]
user = site1
group = site1
listen = /run/php/php8.1-fpm-site1.sock
pm = dynamic
pm.max_children = 10
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
php_admin_value[memory_limit] = 128M
php_admin_value[max_execution_time] = 60
php_value[upload_max_filesize] = 20M
После добавления пула необходимо перезапустить php-fpm и настроить веб-сервер на использование соответствующего сокета.
Частые ошибки:
- Конфликт портов или сокетов, если несколько пулов слушают на одном адресе.
- Неправильные права доступа к сокету (должен быть доступен пользователю веб-сервера).
- Перегрузка сервера из-за слишком большого числа дочерних процессов в пуле.
Как передать настройки PHP через Nginx с помощью fastcgi_param?
В Nginx, работающем с PHP-FPM, можно задать переменные PHP_VALUE или PHP_ADMIN_VALUE в блоке location ~ \.php$. Эти переменные передаются через FastCGI и интерпретируются PHP как директивы.
Случай использования: управление настройками PHP в конфигурации виртуального хоста без создания дополнительных файлов.
Пример в конфигурации Nginx:
location ~ \.php$ {
fastcgi_param PHP_VALUE "memory_limit = 256M\nmax_execution_time = 120";
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
# ...
}
Несколько директив разделяются символом новой строки (\n). Также можно использовать PHP_ADMIN_VALUE для директив, доступных только администратору.
Проблемы:
- Директивы не должны содержать переносов строк внутри строки; для многострочных значений нужно использовать экранирование.
- Если PHP_VALUE и .user.ini задают одинаковые директивы, приоритет имеет более высокий уровень (php.ini > PHP_VALUE > .user.ini).
- Не все директивы поддерживаются через fastcgi_param (только те, что имеют режим PHP_INI_ALL или PHP_INI_USER).
Практические примеры конфигурирования PHP
В этом разделе представлены расширенные примеры настройки PHP с пояснениями и результатами выполнения.
Пример 1: Настройка сессий через .user.ini и проверка phpinfo()
Цель: изменить путь хранения сессий и время жизни на уровне каталога.
Файл .user.ini:
session.save_path = /tmp/sessions_site1
session.gc_maxlifetime = 86400
session.cookie_lifetime = 0
Создание скрипта для проверки:
<?php
phpinfo(INFO_CONFIGURATION | INFO_VARIABLES);
?>
Результат (часть вывода):
session.save_path => /tmp/sessions_site1 session.gc_maxlifetime => 86400 session.cookie_lifetime => 0
Пояснение: изменения в .user.ini применяются автоматически; если путь к сессиям не существует, PHP создаст его (если есть права). Рекомендуется проверять наличие каталога.
Пример 2: Динамическое изменение memory_limit в зависимости от IP-адреса
Цель: для администраторов (определённый IP) выделять больше памяти.
<?php
$admin_ips = ['192.168.1.100', '10.0.0.1'];
if (in_array($_SERVER['REMOTE_ADDR'], $admin_ips)) {
ini_set('memory_limit', '1G');
ini_set('max_execution_time', 600);
} else {
ini_set('memory_limit', '128M');
ini_set('max_execution_time', 30);
}
// далее код, который выполняет разные операции в зависимости от роли
?>
Результат: для обычных пользователей память ограничена 128 МБ, для администраторов выделяется 1 ГБ. Ограничение времени также различное.
Предостережение: такой подход может быть обойдён, если IP подделывается через прокси; лучше использовать аутентификацию.
Пример 3: Настройка пула PHP-FPM для изоляции ресурсов с ограничением по времени
Цель: создать два пула для разных сайтов с разными лимитами.
Конфигурация пула site2:
[site2]
user = site2
group = site2
listen = /run/php/php8.1-fpm-site2.sock
pm = ondemand
pm.max_children = 5
pm.process_idle_timeout = 10s
php_admin_value[memory_limit] = 256M
php_admin_value[max_execution_time] = 30
php_admin_value[request_terminate_timeout] = 30
Пояснение: pm = ondemand создаёт процессы только при необходимости; request_terminate_timeout принудительно завершает скрипт при превышении времени, предотвращая зависание.
Проверка: создадим скрипт, который намеренно долго выполняется:
<?php
sleep(40);
echo "Done";
?>
Результат: скрипт будет прерван через 30 секунд (если request_terminate_timeout не больше max_execution_time). В логах PHP-FPM появится сообщение о превышении времени.
Пример 4: Использование PHP_VALUE в Nginx для включения отображения ошибок только для разработки
Цель: на staging-сервере показывать ошибки, на production - скрывать.
Конфигурация для staging (выборочно):
server {
listen 80;
server_name staging.example.com;
root /var/www/staging;
location ~ \.php$ {
fastcgi_param PHP_VALUE "display_errors = On\nerror_reporting = E_ALL";
fastcgi_param PHP_ADMIN_VALUE "display_errors = On";
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
include fastcgi_params;
}
}
Результат: на staging отображаются все ошибки; на production в аналогичной конфигурации стоит display_errors = Off и error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT.
Важно: PHP_ADMIN_VALUE имеет более высокий приоритет, чем PHP_VALUE, поэтому если обе заданы, то используется та, что последняя в порядке обработки.