Конфигурация 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, поэтому если обе заданы, то используется та, что последняя в порядке обработки.

Файл настроек PHP - comments

En
файл настройки php (php)