Если при открытии страницы появляется белый экран, а в журнале ошибок видна строка Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes), значит, PHP-скрипт упёрся в выделенный ему лимит памяти. Первое число — это лимит в байтах: 134217728 байт ровно 128 МБ. Второе — размер последнего запроса памяти, обычно совсем небольшой, и о корне проблемы он ничего не говорит. Решать такую ошибку можно двумя путями: поднять лимит или найти код, который тратит слишком много памяти. Часто нужно и то и другое.
Что такое memory_limit и зачем он нужен
memory_limit задаёт максимальный объём оперативной памяти, который может использовать один PHP-запрос — одно открытие страницы или один запуск скрипта. Это защитный механизм: чтобы ошибочный цикл или бесконечная рекурсия не заняли всю память сервера и не остановили другие сайты, PHP сам прерывает такой скрипт. Поэтому ставить значение -1, то есть без ограничений, — плохая идея, особенно на виртуальном хостинге. Обычному сайту хватает 128 МБ, для тяжёлых CMS и интернет-магазинов распространено значение 256 МБ, а для крупного импорта или обработки изображений временно может понадобиться 512 МБ.
Проще всего узнать текущее значение через временный файл. После проверки обязательно удалите его: phpinfo() раскрывает много информации о сервере.
<?php
echo ini_get('memory_limit');
// или полная информация: phpinfo();
Где увеличить лимит
Какой способ сработает, зависит от того, в каком режиме PHP запущен на сервере. На большинстве хостингов PHP работает отдельным процессом (PHP-FPM или CGI), на некоторых — модулем Apache. Если выбрать неподходящий способ, настройка либо будет проигнорирована, либо весь сайт начнёт отдавать ошибку 500.
Настройки PHP в панели хостинга
Самый надёжный путь — панель хостинга. В ISPmanager для каждого сайта можно изменить версию PHP и основные параметры, в том числе memory_limit (какие параметры доступны, может зависеть от тарифа). Клиенты sayt.uz входят в панель со страницы хостинга в кабинете sayt.uz. Значение из панели записывается в правильный конфигурационный файл и работает при любом режиме PHP.
Файл .user.ini (для PHP-FPM и CGI)
Если PHP работает в режиме FPM или CGI, можно создать в папке сайта файл .user.ini с нужным параметром. PHP перечитывает его не на каждом запросе, а с заданным интервалом (по умолчанию 300 секунд), поэтому изменение вступит в силу через несколько минут:
; .user.ini
memory_limit = 256M
.htaccess (только в режиме модуля Apache)
Во многих советах в интернете предлагают добавить в .htaccess строку php_value. Это работает только тогда, когда PHP подключён как модуль Apache (mod_php). В режиме FPM или CGI Apache не знает такой директивы, и весь сайт выдаёт ошибку 500. Если после добавления строки сайт упал, сразу удалите её и используйте .user.ini:
# .htaccess
php_value memory_limit 256M
В коде и в WordPress
Для отдельных скриптов лимит можно поднять прямо в коде. Это удобно для одной тяжёлой задачи, например формирования отчёта, — остальные страницы остаются с обычным лимитом. Если администратор сервера жёстко зафиксировал значение, способ не сработает:
ini_set('memory_limit', '512M');
В WordPress есть две собственные константы. WP_MEMORY_LIMIT действует для обычных страниц сайта, WP_MAX_MEMORY_LIMIT — для админки и тяжёлых задач вроде обработки изображений. Их прописывают в wp-config.php перед строкой «That's all, stop editing». Выше серверного лимита PHP они подняться не могут: если сервер даёт 128 МБ, запись 512 МБ в WordPress ничего не изменит.
define('WP_MEMORY_LIMIT', '256M');
define('WP_MAX_MEMORY_LIMIT', '512M');
Когда увеличение лимита не решение
Если вы подняли лимит с 256 МБ до 512 МБ, потом до 1 ГБ, а ошибка всё равно возвращается, проблема в коде. Типичные причины:
- Загрузка целой таблицы в массив одним запросом, например десятков тысяч заказов через
fetchAll(). - Обработка большой фотографии через GD: снимок 6000x4000 пикселей на диске весит несколько мегабайт, но в памяти на каждый пиксель нужно несколько байт, и это легко превышает 100 МБ.
- Бесконечная рекурсия или хук, вызывающий сам себя, — здесь закончится любой объём памяти.
- Конфликтующие или плохо написанные плагины.
Чтобы понять, какая часть кода съедает память, расставьте замеры. Функция memory_get_peak_usage(true) возвращает максимальный расход памяти скриптом на текущий момент:
error_log('Память: ' . round(memory_get_peak_usage(true) / 1048576, 1) . ' MB');
При работе с большими таблицами резко снижает расход обработка порциями. Вместо сбора всего результата в массив читайте строки по одной или работайте пачками по 500–1000 записей через LIMIT и OFFSET.
Пример: экспорт в интернет-магазине в Ташкенте
Магазин бытовой техники в Ташкенте example.uz работает на WooCommerce и каждую неделю выгружает все товары в Excel. Когда товаров стало больше 12 тысяч, страница экспорта начала падать с ошибкой «Allowed memory size». Разработчик сначала поднял memory_limit до 256 МБ через панель — это временно помогло. Затем замеры через memory_get_peak_usage показали, что плагин экспорта загружает в память все товары сразу вместе с изображениями и метаданными. После включения в настройках плагина экспорта порциями по 500 штук расход стабилизировался около 90 МБ, и дальше поднимать лимит не потребовалось.
Лимиты тарифа хостинга
На виртуальном хостинге помимо настройки PHP может действовать общий лимит памяти тарифа. Если memory_limit достаточен, но при наплыве посетителей сайт всё равно тормозит или выдаёт ошибки, дело может быть не в одном скрипте, а в суммарном расходе всех одновременно работающих процессов. Первые шаги здесь — просмотреть журналы, отключить лишние плагины и включить кеширование. Если проект действительно вырос, пора подумать о более мощном тарифе или VPS. Вопросы о конкретных лимитах можно задать в техподдержку через тикет в кабинете sayt.uz.