PHP: полный мануал с примерами, функциями и ООП
Практический мануал PHP: от переменных и читаемого кода до безопасных форм, интеграций, базы данных и ООП на примере магазина. Учебный маршрут, поиск функций, подробные примеры, разбор ошибок и исходники для скачивания.

Дерево руководства
Глава 135 · От запуска скрипта к эксплуатации сервера
OPcache: кеш PHP-кода, прогрев, обновление, preload и JIT
Все функции OPcache и полный набор настроек: понимаем подготовку кода, область кеша, смену релиза и отличие JIT от кеширования.
Что ускоряет OPcache: готовить код один раз, исполнять для каждого запроса
Интернет-магазин принимает много запросов, каждый использует одни и те же PHP-файлы. Перед исполнением движок разбирает исходник и готовит инструкции. OPcache позволяет сохранить эту подготовленную форму и использовать её снова. Если посетители разные, корзины всё равно вычисляются отдельно: кеш инструкций не хранит готовую корзину первого посетителя.
OPcache сохраняет подготовленный к исполнению PHP-код. При следующем запросе движок может взять готовые инструкции, но сами действия скрипта выполняются снова: SQL, HTTP-запросы, циклы и вывод не превращаются в готовый HTML-кеш. Экземпляр кеша связан с конкретным окружением PHP; консольный вызов не является удалённым управлением всеми PHP-FPM серверами.
- Исходник calculation.php
- Первый раз: разбор → компиляция → кеш
- Следующий раз: готовые инструкции из кеша
- Каждый раз: выполнение с текущими данными
| Механизм | Что хранит и зачем |
|---|---|
| OPcache | Подготовленные инструкции PHP, чтобы не разбирать один исходник заново. |
| Кеш данных | Например, результат дорогого запроса; его срок жизни и инвалидирование определяет приложение. |
| Кеш страницы/CDN | Готовый HTTP-ответ или ресурс; важны пользователь, cookies и политика кеширования. |
| JIT | Машинный код выбранных участков; не заменяет остальные виды кеша. |
| Preload | Постоянные объявления классов/функций при старте процесса; отдельный lifecycle. |
<?php
declare(strict_types=1);
$configuration = opcache_get_configuration();
if ($configuration === false) throw new RuntimeException('Нет доступа к OPcache API');
echo $configuration['directives']['opcache.enable'] ? "Подготовленный код кешируется\n" : "Кеш отключён\n";
Ожидаемый результат
Подготовленный код кешируется
Массив configuration — диагностические данные текущего PHP. Эта строка не замеряет ускорение сайта; она только подтверждает настройку своей лаборатории.
PHP 8.5 и прежние версии: разные способы подключения
OPcache входит в PHP с 5.5; для 5.2–5.4 существовало отдельное PECL-расширение. Начиная с PHP 8.5 он всегда встроен в бинарник и загружен. Это не означает, что кеширование обязательно включено: opcache.enable и enable_cli продолжают управлять работой. В 8.5 строки zend_extension=opcache.so или zend_extension=php_opcache.dll вызывают предупреждение и должны быть удалены из старой конфигурации при миграции.
Для PHP до 8.5 действовал способ сборки shared extension с --enable-opcache, особенно при --disable-all, и загрузкой через zend_extension с путём к opcache.so/php_opcache.dll. Это Zend-расширение, поэтому обычное extension= не равнозначная замена. При совместном использовании с Xdebug OPcache загружается раньше. На странице installation официального manual ещё присутствует историческая инструкция; для 8.5 применяются более новые правила migration85.
<?php
declare(strict_types=1);
var_dump(extension_loaded('Zend OPcache'));
var_dump(function_exists('opcache_get_status'));
echo ini_get('opcache.enable_cli') === '1' ? "CLI-кеш включён\n" : "CLI-кеш выключен\n";
Ожидаемый результат
bool(true)
bool(true)
CLI-кеш включён
В лаборатории enable_cli задан параметром запуска. В обычной установке default0; наличие функции в PHP8.5 не доказывает, что опкоды текущей команды кешируются.
php -d opcache.enable_cli=1 -d opcache.jit=disable -d opcache.jit_buffer_size=0 -d opcache.file_update_protection=0 -d opcache.cache_id=phpmanual-local -d opcache.file_cache=C:/php-lab/cache example.php
Для PHP8.5 сначала создают отдельную доступную C:/php-lab/cache и помещают скачанные файлы примера в свою учебную директорию. На PHP≤8.4 дополнительно требуется совместимо загруженный OPcache. Команда не изменяет серверный ini. На Unix cache_id не используется, выбирают отдельный CLI-процесс и свой путь file_cache.
Учебная file_update_protection=0 позволяет сразу кешировать созданные файлы. На работающем сайте это решение связывают с атомарной публикацией исходников. Не копируйте весь профиль лаборатории в production. Настройки памяти, числа файлов и проверки изменений выбираются по приложению; старое fast_shutdown=1 из исторических рекомендаций более не действует.
Прогрев, изменение кода и разные экземпляры кеша
После старта новый экземпляр памяти пустой. Первые запросы либо специальный прогрев наполняют его. При изменении исходников важно, когда PHP заметит новый код. validate_timestamps и revalidate_freq задают автоматическую проверку; при отключённой проверке обновление входит в процесс развёртывания.
<?php
declare(strict_types=1);
$path = __DIR__ . '/calculation.php';
// Только наш учебный файл: исключаем защиту от совсем нового timestamp.
touch($path, time() - 60);
opcache_compile_file($path);
echo require $path, "\n";
echo require $path, "\n";
Ожидаемый результат
42
42
Готовый байткод используется снова, но require исполняет код каждый раз. Это не require_once и не мемоизация результата.
На Linux CLI не управляет in-memory кешем независимого PHP-FPM мастера. Несколько серверов за балансировщиком имеют свои экземпляры; несколько пулов не стоит автоматически считать независимыми кешами без знания процесса запуска. На Windows область разделения определяется также SAPI, пользователем и cache_id. Поэтому «opcache_reset вернул true в консоли» не равно «все посетители уже видят новый релиз».
Для одного изменённого файла есть invalidate, для памяти всего экземпляра — reset, для preloaded-объявлений требуется restart процесса. Файловый кеш — отдельный второй уровень: reset его не удаляет, тогда как актуальный invalidate обрабатывает соответствующую файловую запись. Политика обновления должна быть согласована с конкретной версией и способом развёртывания, а не случайным публичным URL сброса.
Полная таблица настроек: назначение, версия и область изменения
INI_SYSTEM означает настройку при запуске сервера/процесса; ini_set в странице её не заменяет. INI_ALL разрешает runtime-изменение только в рамках специальных правил директивы. Значения в таблице — исходные значения документации, а не готовый универсальный production-профиль. В пакетах ОС они могут быть изменены.
| Параметр и исходное значение | Область | Для чего нужен |
|---|---|---|
| opcache.enable = 1 | ALL | Включение кеширования и оптимизации. Через ini_set можно выключить, но нельзя включить обратно в уже запущенном скрипте. |
| opcache.enable_cli = 0 | SYSTEM | Отдельное разрешение CLI; оно не управляет PHP-FPM. В 7.1.2–7.1.6 стандартное значение было 1. |
| opcache.memory_consumption = 128 | SYSTEM | МиБ общей памяти для OPcache, минимум 8. При JIT дополнительно нужен его буфер; подбор зависит от кодовой базы. |
| opcache.interned_strings_buffer = 8 | SYSTEM | МиБ для повторно используемых строк. С 8.4 максимум 32767 на 64 бит и 4095 на 32 бит; раньше 4095 везде. |
| opcache.max_accelerated_files = 10000 | SYSTEM | Предельное число ключей. Диапазон 200…1000000, вне его значение ограничивается; фактическая таблица округляется до подходящего простого размера. |
| opcache.max_wasted_percentage = 5 | SYSTEM | Допустимая доля wasted памяти перед планированием restart при недостатке свободной. Верхний предел 50, это не процент memory_limit скрипта. |
| opcache.use_cwd = 1 | SYSTEM | Добавлять рабочую директорию к ключу скрипта. Отключение может столкнуть одинаковые относительные имена в разных каталогах. |
| opcache.validate_timestamps = 1 | ALL | Проверять изменение исходных файлов. При 0 обновления требуют согласованного invalidate/reset или перезапуска нужного процесса. |
| opcache.revalidate_freq = 2 | ALL | Интервал проверки mtime в секундах; 0 проверяет каждый запрос. Не действует при validate_timestamps=0. |
| opcache.revalidate_path = 0 | ALL | Повторно разрешать пути поиска. При 0 уже закешированное имя из include_path может скрыть другой одноимённый файл в пути поиска. |
| opcache.save_comments = 1 | SYSTEM | Сохранять doc comments. Их удаление может сломать аннотации, Reflection и зависящие от них библиотеки; это не автоматическая рекомендация оптимизации. |
| opcache.fast_shutdown = 0, удалена | SYSTEM | Удалена с 7.2: вариант механизма встроен в движок. Не добавлять в современный ini по старой статье. |
| opcache.enable_file_override = 0 | SYSTEM | Разрешить проверкам file_exists/is_file/is_readable использовать кеш скриптов. Без проверки timestamps возможны устаревшие ответы. |
| opcache.optimization_level = 0x7FFEBFFF | SYSTEM | Битовая маска проходов оптимизатора. До 7.3 стандарт был 0x7FFFBFFF; небезопасные биты меняют предположения о поведении кода. |
| opcache.inherited_hack = 1, удалена | SYSTEM | Историческая игнорируемая настройка; удалена в 7.3. |
| opcache.dups_fix = 0 | ALL | Старый специальный обход Cannot redeclare class. Причину повторного объявления сначала исправляют в загрузке кода. |
| opcache.blacklist_filename = пусто | SYSTEM | Файл перечня исходников, которые не следует ускорять; строки поддерживают префиксы/маски, ; начинает комментарий. |
| opcache.max_file_size = 0 | SYSTEM | Максимальный размер исходного файла для кеша в байтах; 0 не вводит ограничение. Это не максимальный HTTP upload. |
| opcache.consistency_checks = 0, удалена | ALL | Историческая проверка checksum каждые N запросов. Отключена с 8.1.18/8.2.5, удалена в 8.3; отладочный расход не ускорение. |
| opcache.force_restart_timeout = 180 | SYSTEM | Секунды ожидания запланированного restart; после предела возможна остановка процессов, удерживающих блокировки. Не поддерживается Windows; события журналируются при verbosity≥2. |
| opcache.error_log = пусто | SYSTEM | Путь журнала OPcache; пустое значение направляет записи в stderr, часто журнал веб-сервера. |
| opcache.log_verbosity_level = 1 | SYSTEM | 0 — fatal, 1 — errors, 2 — warnings, 3 — информация, 4 — отладка. Подробный журнал требует контроля объёма. |
| opcache.record_warnings = 0 | SYSTEM | С 8.0 сохранять compile-time warnings и повторять при загрузке из кеша. Важно для одинаковой диагностики холодного и прогретого кода. |
| opcache.preferred_memory_model = пусто | SYSTEM | Автовыбор модели общей памяти обычно правильный; специальные значения mmap/shm/posix/win32 зависят от системы. |
| opcache.protect_memory = 0 | SYSTEM | Защита shared memory от неожиданных записей для внутренней отладки. Не прикладная проверка безопасности загружаемых файлов. |
| opcache.mmap_base = null | SYSTEM | Только Windows: базовый адрес отображения для решения конфликтов reattach. Не универсальная настройка, которую копируют с чужого компьютера. |
| opcache.restrict_api = пусто | SYSTEM | Разрешённый префикс пути скриптов, вызывающих API. Пусто — без такого ограничения; не заменяет авторизацию HTTP-доступа. |
| opcache.file_update_protection = 2 | ALL | Не кешировать совсем недавно изменённые файлы, чтобы не схватить неполное обновление. 0 допустим при гарантированно атомарной публикации файлов. |
| opcache.huge_code_pages = 0 | SYSTEM | Перенос text segment бинарника PHP в huge pages. Нужна поддержка ОС; это не тот же сегмент, что memory_consumption. Linux с 7.0, FreeBSD с 7.4; при отказе remap warning. |
| opcache.lockfile_path = /tmp | SYSTEM | Абсолютная директория shared lockfiles на Unix-подобной системе. Не произвольный файл приложения. |
| opcache.opt_debug_level = 0 | SYSTEM | С 7.1 дампы инструкций оптимизатора: 0x10000 до оптимизации, 0x20000 после. Для диагностики, не публичного вывода страницы. |
| opcache.file_cache = null / пусто | SYSTEM | Существующая доступная директория второго уровня на диске. Пустое значение отключает этот уровень; защищайте доступ к подготовленному коду. |
| opcache.file_cache_only = 0 | SYSTEM | 1 использует файловый кеш вместо общей памяти. До 8.1 при выключении режима с заполненным кешем требовалась его ручная очистка. |
| opcache.file_cache_consistency_checks = 1 | SYSTEM | Проверять контрольную сумму при загрузке подготовленного файла. Это отдельная настройка, не удалённая consistency_checks. |
| opcache.file_cache_fallback = 1 | SYSTEM | Только Windows: при неудачном подключении общей памяти переходить к file_cache_only для процесса. Требует заданного file_cache; отключение может помешать старту. |
| opcache.validate_permission = 0 | SYSTEM | Проверять права кешированного файла относительно текущего пользователя; с 7.0.14. |
| opcache.validate_root = 0 | SYSTEM | Защищать имена в chroot от столкновений и доступа к файлам вне корня; включают для chroot-окружений. С 7.0.14. |
| opcache.preload = пусто | SYSTEM | С 7.4 путь startup-скрипта для постоянных объявлений. На Windows preload не поддерживается; код выполняется при запуске сервера. |
| opcache.preload_user = пусто | SYSTEM | Пользователь запуска preload в Unix. Root по умолчанию запрещён; с 8.3 для CLI/phpdbg отдельное значение не требуется лишь ради root-старта. |
| opcache.cache_id = пусто | SYSTEM | Windows с 7.4: один пользователь, SAPI и cache_id делят экземпляр. Для изолированных приложений задают разные ID; в IIS возможен APP_POOL_ID. |
| opcache.jit = disable | ALL | С 8.0 выбор режима JIT; до 8.4 default tracing. disable запрещает последующее включение в runtime, off оставляет такую возможность. |
| opcache.jit_buffer_size = 64M | SYSTEM | Байты/суффикс размера для машинного кода. 0 отключает JIT; до 8.4 default был 0. Сам ненулевой размер не отменяет jit=disable. |
| opcache.jit_debug = 0 | ALL | Битовая маска отладочного вывода JIT из ZEND_JIT_DEBUG_* в zend_jit.h конкретной версии. |
| opcache.jit_bisect_limit = 0 | ALL | Остановить компиляцию после N функций для поиска проблемного места. Работает с trigger 0 или 1, не универсальный лимит tracing. |
| opcache.jit_prof_threshold = 0.005 | ALL | Для первого profiling-запроса доля вызовов, выше которой функция hot. 0.005 соответствует 0.5% всех вызовов. |
| opcache.jit_max_root_traces = 1024 | SYSTEM | Предел корневых трасс; после достижения новые корневые трассы не компилируются. |
| opcache.jit_max_side_traces = 128 | SYSTEM | Предел боковых трасс одной root trace, то есть альтернативных путей от неё. |
| opcache.jit_max_exit_counters = 8192 | SYSTEM | Общий предел счётчиков выходов для боковых трасс всех корневых путей. |
| opcache.jit_hot_loop = 61 | SYSTEM | Итерации до hot loop. В 8.0–8.4 default64, с 8.5 —61. Рекомендуемое простое число снижает совпадения с периодом циклов. |
| opcache.jit_hot_func = 127 | SYSTEM | Вызовы до hot function; общие правила диапазона 0…255 описаны ниже. |
| opcache.jit_hot_return = 8 | SYSTEM | Возвраты до hot return; 0 отключает трассировку соответствующего вида. |
| opcache.jit_hot_side_exit = 8 | ALL в 8.5.11 | Выходы до hot side exit. Таблица manual указывает SYSTEM, но tagged PHP 8.5.11 регистрирует ALL; проверяйте свою сборку. |
| opcache.jit_blacklist_root_trace = 16 | ALL | Сколько попыток компиляции root trace допускается до внесения её в blacklist. |
| opcache.jit_blacklist_side_trace = 8 | ALL | Аналогичный предел попыток для боковой трассы. |
| opcache.jit_max_loop_unrolls = 8 | ALL | Попытки развёртки цикла в боковой трассе, чтобы достигнуть root trace и замкнуть внешний цикл. |
| opcache.jit_max_recursive_calls = 2 | ALL | Предел развёрнутых рекурсивных вызовов при компиляции, не лимит глубины рекурсии вашего PHP-кода. |
| opcache.jit_max_recursive_returns = 2 | ALL | Предел развёртки рекурсивных возвратов, не количество разрешённых return в программе. |
| opcache.jit_max_polymorphic_calls = 2 | ALL | Попытки встроить динамические/методные вызовы с разными целями; выше предела считаются megamorphic и не встраиваются. |
| opcache.jit_max_trace_length = 1024 | ALL, tagged 8.5.11 | Дополнительная настройка реализации: предел длины трассы. Допускается диапазон от4 до ZEND_JIT_TRACE_MAX_LENGTH; не выбирайте значение вне диапазона своей версии. |
Фактическая ёмкость max_accelerated_files выбирается из 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987, 262237, 524521, 1048793: ближайшее не меньше заданного значения после ограничения допустимого диапазона. Поэтому число в статусе может отличаться от ini. При нехватке памяти рост числа ключей сам по себе не поможет.
jit_hot_loop, jit_hot_func, jit_hot_return и jit_hot_side_exit принимают 0…255. Вне диапазона используется стандартное значение; 0 выключает соответствующий вид трассировки. Список настроек JIT зависит от поддержки в сборке. Порог компиляции не является таймаутом или ограничением пользовательского цикла.
При validate_timestamps=0 отдельные проверки времени всё ещё могут происходить во время компиляции из-за file_update_protection/max_file_size. Это не означает автоматическую актуализацию всего кеша. Подготовьте воспроизводимый план deploy до отключения проверок. Параметры shared memory и huge pages имеют разные роли: общий сегмент может пытаться использовать huge pages и без копирования text segment директивой huge_code_pages.
Проходы оптимизатора и их битовая маска
Оптимизатор преобразует PHP-инструкции перед сохранением. Маска optimization_level задаёт проходы, а не уровень качества JPEG и не права доступа. Стандартная комбинация сохраняет поведение обычного кода; особые небезопасные предположения полезны только для внутренней диагностики.
| Бит / проход | Преобразование |
|---|---|
| 0 / PASS_1 | Локальные упрощения соседних инструкций. |
| 1 / PASS_2 | Исторический проход объединён с PASS_1. |
| 2 / PASS_3 | Упрощение переходов. |
| 3 / PASS_4 | Оптимизация вызовов. |
| 4 / PASS_5 | Преобразования по графу потока управления. |
| 5 / PASS_6 | Анализ потока данных. |
| 6 / PASS_7 | Использовать граф вызовов для SSA-оптимизаций. |
| 7 / PASS_8 | Распространение известных констант по достижимым веткам. |
| 8 / PASS_9 | Оптимизация временных переменных. |
| 9 / PASS_10 | Удаление пустых NOP. |
| 10 / PASS_11 | Уплотнение литералов. |
| 11 / PASS_12 | Расчёт размера стека вызова заранее. |
| 12 / PASS_13 | Удаление неиспользуемых переменных. |
| 13 / PASS_14 | Удаление недостижимого кода. |
| 14 / PASS_15 | Подстановка объявлений констант без сохранения всех runtime-условий; unsafe, по умолчанию выключен. |
| 15 / PASS_16 | Встраивание тривиальных функций в рамках оптимизации вызовов. |
| 16 / специальный флаг | Игнорировать перегрузку операторов; unsafe и по умолчанию выключен. |
Например, агрессивная подстановка константы может проигнорировать порядок её объявления. Предположение об отсутствии перегрузки арифметики некорректно для GMP/BCMath-объектов с do_operation. Не включайте все биты в надежде получить «максимальную скорость»: исключённые биты исключены по смысловой причине. Типовая оптимизация проекта начинается с измерений реальных узких мест.
JIT: режимы, пороги и реальная польза
JIT переводит подходящие участки в машинный код. OPcache без JIT всё равно полезен: он исключает повторную подготовку PHP-исходников. Для страницы, которая большую часть времени ждёт SQL или API, JIT не устраняет это ожидание. Больше шансов на выигрыш у длительных вычислительных участков; измерять надо реальную нагрузку после прогрева.
| Режим jit | Поведение |
|---|---|
| disable | Полностью выключен, включить в runtime нельзя; default с PHP 8.4. |
| off | Сейчас выключен, runtime-включение разрешено при подходящем буфере/сборке. |
| tracing / on | Собирать и компилировать горячие пути; CRTO1254. |
| function | Компилировать функции; CRTO1205. |
Продвинутая числовая запись CRTO содержит четыре независимые цифры. C:0 без специальных CPU-оптимизаций,1 использует AVX при доступности. R:0 без распределения регистров,1 локальное,2 глобальное. T:0 все функции при загрузке,1 при первом вызове,2 профиль первого запроса с последующей компиляцией горячих функций,3 профилирование горячих функций в ходе работы,4 не используется,5 tracing. O:0 без JIT,1 обычные VM-handlers,2 их встраивание,3 вывод типов,4 граф вызовов,5 оптимизация всего скрипта.
Нулевой jit_buffer_size отключает JIT, ненулевой резервирует память под машинный код. С PHP 8.4 ошибка инициализации включённого JIT прерывает старт fatal error: сначала проверяют профиль на отдельном экземпляре. Для расследования есть jit_debug, jit_bisect_limit и opcache_jit_blacklist. Примеры этой главы не выдают обычное CLI-исполнение за доказательство ускорения JIT.
Preload: чем постоянные объявления отличаются от обычного кеша
С PHP 7.4 startup-скрипт может подготовить функции, классы, интерфейсы и трейты в постоянную память. Они доступны следующим запросам без обычной загрузки объявления. Глобальные константы таким же образом не становятся preloaded. Выигрыш оплачивается базовым потреблением памяти и более строгим обновлением: старые preloaded-объявления убирает restart процесса, а не замена файла на диске.
На Windows preload не поддерживается. Для обычной короткой CLI-команды польза мала: процесс сразу завершится. Исключение в документации — отдельные задачи FFI-библиотек. Практический смысл в долгоживущем серверном процессе, где одни объявления используются многими запросами. Не обязательно загружать весь vendor: измеряют реально нужную часть и базовую память.
opcache.preload=/srv/shop/preload.php
opcache.preload_user=www-data
Фрагмент ini для сервера, где существует пользователь www-data и указанный доверенный скрипт. Это пример контекста, а не команда для текущей Windows. Изменение требует перезапуска обслуживающего PHP-процесса.
<?php
declare(strict_types=1);
// preload.php: выполняется при старте поддерживаемого Unix SAPI.
$files = [__DIR__ . '/src/Price.php', __DIR__ . '/src/Cart.php'];
foreach ($files as $path) {
if (!opcache_compile_file($path)) throw new RuntimeException('Preload не завершён');
}
Два пути выбирает приложение. Файлы должны содержать пригодные для preload объявления и быть доступны startup-пользователю. Здесь проверен синтаксис; Windows preload не выдаётся за реально запущенный.
Startup-файл сам исполняется. Если он использует include/require, тела подключённых файлов тоже исполняются и цепочки их include обрабатываются. Это позволяет условные объявления, но также запускает побочные действия. opcache_compile_file не выполняет тело и даёт больше свободы порядка компиляции, в том числе файлов с наследованием. Для include базовый класс должен быть определён до потомка; условные объявления требуют исполнения нужной ветки.
Если последующий запрос включает уже preloaded-файл, его основное тело всё равно может исполниться, а постоянные символы не объявляются заново. include_once не делает факт preloading равнозначным прошлому обычному include этого запроса. Иногда повторное включение нужно именно ради глобальных констант или runtime-инициализации — поэтому файлы объявлений и побочные действия стоит разделять осмысленно.
При старте FPM от root выполняйте preload с подходящим непривилегированным пользователем. Явное preload_user=root разрешает root-исполнение, но это не рекомендуемый универсальный профиль. С 8.3 правила CLI/phpdbg допускают root-start без этой отдельной настройки; это исключение не следует переносить на серверную модель. Зависимости и объём постоянной памяти проверяют на отдельном окружении перед выпуском.
Полный список функций OPcache по задачам
| Задача | API |
|---|---|
| Подготовить код без выполнения | opcache_compile_file |
| Проверить подготовленность в памяти/на диске | opcache_is_script_cached · opcache_is_script_cached_in_file_cache |
| Посмотреть настройки и состояние | opcache_get_configuration · opcache_get_status |
| Обновить один файл или память экземпляра | opcache_invalidate · opcache_reset |
| Диагностировать одну tracing-JIT функцию | opcache_jit_blacklist |
OPcache не предлагает классы для вашей корзины или платежа. Его функции относятся к подготовке и эксплуатации PHP-кода, а не к бизнес-данным. Подробные карточки содержат различия return, области действия и версии.
Практический маршрут: после deploy видно старую страницу
| Шаг | Что отличаем |
|---|---|
| 1. Проверить обслуживающий узел | Запрос действительно попал в новый релиз и нужный PHP-процесс? Балансировщик может вести на разные версии. |
| 2. Разделить уровни кеша | Это HTML/CDN/browser кеш, данные приложения либо PHP-байткод? Очистка одного не очищает все. |
| 3. Увидеть настройки нужного SAPI | validate_timestamps/revalidate_freq/file_cache/preload определяют жизненный цикл. CLI-конфигурация может отличаться. |
| 4. Обновить контролируемо | Действовать выбранной схемой развёртывания: invalidate, reset или restart для соответствующего случая. |
| 5. Проверить результат снаружи | Убедиться, что нужные узлы отвечают новым релизом; отдельный bool из административного скрипта недостаточен. |
Мониторинг должен отличать нормальный холодный старт от постоянных промахов и нехватки памяти. Счётчики oom_restarts/hash_restarts/manual_restarts, заполнение памяти и число ключей помогают выбрать, какой предел исследовать. Нельзя из одного процента hit rate заключить, что приложение быстро: медленный SQL, внешний HTTP и тяжёлые циклы остаются. Их разбирает раздел измерения производительности.
Примеры не включают JIT ради красивого числа ускорения и не сбрасывают кеш опубликованного сайта. Чтобы измерить эффект, сравнивают одинаковую нагрузку, прогретость, версии и ресурсы. Сначала устраняют причину задержки, затем выбирают соответствующий вид кеша.
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
opcache_compile_fileСкомпилировать файл для прогрева без исполнения его тела.
PHP 5.5.5+ · Zend OPcache
opcache_compile_file(string $filename): boolСкомпилировать файл для прогрева без исполнения его тела.
OPcache сохраняет подготовленный к исполнению PHP-код. При следующем запросе движок может взять готовые инструкции, но сами действия скрипта выполняются снова: SQL, HTTP-запросы, циклы и вывод не превращаются в готовый HTML-кеш. Экземпляр кеша связан с конкретным окружением PHP; консольный вызов не является удалённым управлением всеми PHP-FPM серверами.
| Часть вызова | Контракт |
|---|---|
| filename | Путь к доверенному PHP-скрипту. |
| Результат | true — компиляция успешна; false — неудача. |
| Побочные действия | Тело скрипта не исполняется; параметры кеша всё равно определяют возможность сохранения. |
В обычном запросе файл компилируется перед выполнением. При прогреве можно заранее подготовить известные файлы приложения, не исполняя их основное тело. Это полезно после старта нового пула работников; прогревать следует доверенный список, а не путь из GET.
<?php
declare(strict_types=1);
$path = __DIR__ . '/calculation.php';
// Только наш учебный файл: исключаем защиту от совсем нового timestamp.
touch($path, time() - 60);
var_dump(opcache_compile_file($path));
$answer = require $path;
echo $answer, "\n";
Ожидаемый результат
bool(true)
42
calculation.php содержит return 40+2. Вызов compile не возвращает 42: он сообщает успешность компиляции. Значение появляется только после require.
<?php
declare(strict_types=1);
$path = __DIR__ . '/message.php';
touch($path, time() - 60);
opcache_compile_file($path);
echo "После компиляции\n";
$value = require $path;
echo $value, "\n";
Ожидаемый результат
После компиляции
Файл выполнен
42
message.php печатает строку только во время require. Эта граница важна для файлов с побочными действиями: прогрев не должен отправлять письма или создавать заказы.
<?php
declare(strict_types=1);
$files = [__DIR__ . '/calculation.php', __DIR__ . '/message.php'];
foreach ($files as $path) {
touch($path, time() - 60);
if (!opcache_compile_file($path)) throw new RuntimeException('Ошибка прогрева');
echo basename($path), ': ', opcache_is_script_cached($path) ? 'в памяти' : 'не в памяти', "\n";
}
Ожидаемый результат
calculation.php: в памяти
message.php: в памяти
Успешная компиляция и фактическая запись в память — разные наблюдения. Параметры ограничения размера, blacklist, свежести файла и памяти влияют на кеширование.
Ошибка загрузки или компиляции может сопровождаться E_WARNING; не подавляйте её глобально. Успех компиляции не гарантирует отсутствие runtime-ошибок будущего вызова и не заменяет тестирование. В режиме startup-preload эта функция участвует в постоянной загрузке объявлений; это отдельный жизненный цикл, разобранный в главе. Не компилируйте чужой PHP как способ «проверки безопасности»: это доверенный исходный код приложения.
Рядом по задаче: opcache_is_script_cached; opcache_is_script_cached_in_file_cache; opcache_invalidate.
opcache_is_script_cachedПроверить наличие скрипта именно в кеше памяти.
PHP 5.5.11+ · Zend OPcache
opcache_is_script_cached(string $filename): boolПроверить наличие скрипта именно в кеше памяти.
OPcache сохраняет подготовленный к исполнению PHP-код. При следующем запросе движок может взять готовые инструкции, но сами действия скрипта выполняются снова: SQL, HTTP-запросы, циклы и вывод не превращаются в готовый HTML-кеш. Экземпляр кеша связан с конкретным окружением PHP; консольный вызов не является удалённым управлением всеми PHP-FPM серверами.
| Часть вызова | Контракт |
|---|---|
| filename | Путь к скрипту. |
| Результат | true — есть в текущей памяти OPcache, иначе false. |
Эта функция отвечает на конкретный вопрос: есть ли подготовленный скрипт в памяти текущего OPcache. Она не смотрит в HTTP/CDN-кеш и не подтверждает наличие записи в файловом OPcache. Полезна при проверке прогрева или объяснении, почему нужный файл постоянно компилируется.
<?php
declare(strict_types=1);
$path = __DIR__ . '/calculation.php';
// Только наш учебный файл: исключаем защиту от совсем нового timestamp.
touch($path, time() - 60);
var_dump(opcache_is_script_cached($path));
opcache_compile_file($path);
var_dump(opcache_is_script_cached($path));
Ожидаемый результат
bool(false)
bool(true)
Путь относится к отдельной учебной директории, поэтому раньше файла в этом кеше не было. В работающем сервисе исходное состояние может уже быть true.
<?php
declare(strict_types=1);
$path = __DIR__ . '/calculation.php';
// Только наш учебный файл: исключаем защиту от совсем нового timestamp.
touch($path, time() - 60);
opcache_compile_file($path);
$ready = opcache_is_script_cached($path);
echo $ready ? "Расчёт подготовлен\n" : "Нужно проверить прогрев\n";
echo require $path, "\n";
Ожидаемый результат
Расчёт подготовлен
42
Наличие в кеше ускоряет подготовку, но результат вычисления возвращается при выполнении файла. Флаг не является блокировкой: состояние может измениться между проверкой и запросом.
false бывает при выключенном кеше или отсутствии подходящей записи, а не только при отсутствии файла на диске. Не используйте эту функцию вместо is_file/is_readable и не делайте бизнес-логику зависимой от прогретости. Путь и разрешение include_path/cwd должны соответствовать реальному приложению. Ограничение opcache.restrict_api может запретить диагностический вызов.
Рядом по задаче: opcache_compile_file; opcache_is_script_cached_in_file_cache; opcache_get_status.
opcache_is_script_cached_in_file_cacheПроверить подготовленную запись скрипта в файловом кеше.
PHP 8.5+ · Zend OPcache
opcache_is_script_cached_in_file_cache(string $filename): boolПроверить подготовленную запись скрипта в файловом кеше.
OPcache сохраняет подготовленный к исполнению PHP-код. При следующем запросе движок может взять готовые инструкции, но сами действия скрипта выполняются снова: SQL, HTTP-запросы, циклы и вывод не превращаются в готовый HTML-кеш. Экземпляр кеша связан с конкретным окружением PHP; консольный вызов не является удалённым управлением всеми PHP-FPM серверами.
| Часть вызова | Контракт |
|---|---|
| filename | Путь исходного PHP-скрипта. |
| Результат | true — запись обнаружена в file cache, иначе false. |
| Версия | Добавлена в PHP 8.5; проверка памяти вынесена в другую функцию. |
У OPcache есть второй уровень — файлы с подготовленными инструкциями на диске. Они могут пережить завершение процесса, а кеш памяти — нет. Начиная с PHP 8.5 эту часть можно проверить отдельной функцией. Не путайте её с проверкой существования исходного .php файла.
<?php
declare(strict_types=1);
$path = __DIR__ . '/calculation.php';
// Только наш учебный файл: исключаем защиту от совсем нового timestamp.
touch($path, time() - 60);
opcache_compile_file($path);
echo opcache_is_script_cached($path) ? "В памяти\n" : "Не в памяти\n";
echo opcache_is_script_cached_in_file_cache($path) ? "На диске\n" : "Не на диске\n";
Ожидаемый результат
В памяти
На диске
В нашей отдельной лаборатории задана доступная директория opcache.file_cache. При стандартном пустом значении второй результат был бы отрицательным, даже если память прогрета.
<?php
declare(strict_types=1);
$path = __DIR__ . '/calculation.php';
// Только наш учебный файл: исключаем защиту от совсем нового timestamp.
touch($path, time() - 60);
opcache_compile_file($path);
var_dump(opcache_is_script_cached_in_file_cache($path));
opcache_invalidate($path, true);
var_dump(opcache_is_script_cached_in_file_cache($path));
Ожидаемый результат
bool(true)
bool(false)
В PHP 8.5.11 invalidate удалил и соответствующий файловый кеш. Старые советы, что любое управление OPcache затрагивает только память, нельзя без проверки переносить на эту функцию.
Функция возвращает только bool, не путь внутреннего файла и не объём кеша. Имена внутренних каталогов и форматы файлов — детали реализации; не записывайте туда свой PHP-код вручную. Общий opcache_get_status описывает память, а не этот второй уровень. Для версий до 8.5 проверяйте function_exists либо используйте операционные средства наблюдения своей версии.
Рядом по задаче: opcache_is_script_cached; opcache_compile_file; opcache_invalidate.
opcache_invalidateИнвалидировать подготовленный код одного файла.
PHP 5.5+ · Zend OPcache
opcache_invalidate(string $filename, bool $force = false): boolИнвалидировать подготовленный код одного файла.
OPcache сохраняет подготовленный к исполнению PHP-код. При следующем запросе движок может взять готовые инструкции, но сами действия скрипта выполняются снова: SQL, HTTP-запросы, циклы и вывод не превращаются в готовый HTML-кеш. Экземпляр кеша связан с конкретным окружением PHP; консольный вызов не является удалённым управлением всеми PHP-FPM серверами.
| Часть вызова | Контракт |
|---|---|
| filename | Путь изменяемого файла приложения. |
| force | false сверяет время изменения; true принудительно инвалидирует. |
| Результат | true при выполненной операции или отсутствии необходимости; false при недоступном кеше. |
При развёртывании изменился один шаблон. opcache_invalidate делает его кешированную версию непригодной для следующей загрузки, не сбрасывая автоматически всё приложение. Это не подмена уже исполняющегося кода внутри текущего запроса.
<?php
declare(strict_types=1);
$path = __DIR__ . '/calculation.php';
// Только наш учебный файл: исключаем защиту от совсем нового timestamp.
touch($path, time() - 60);
opcache_compile_file($path);
var_dump(opcache_is_script_cached($path));
var_dump(opcache_invalidate($path, true));
var_dump(opcache_is_script_cached($path));
Ожидаемый результат
bool(true)
bool(true)
bool(false)
force=true действует независимо от сравнения времени изменения. Повторная загрузка этого файла будет готовить актуальный код. Другие файлы не перечислялись и не сбрасывались.
<?php
declare(strict_types=1);
$path = __DIR__ . '/calculation.php';
// Только наш учебный файл: исключаем защиту от совсем нового timestamp.
touch($path, time() - 60);
opcache_compile_file($path);
var_dump(opcache_invalidate($path, false));
var_dump(opcache_is_script_cached($path));
Ожидаемый результат
bool(true)
bool(true)
При force=false файл не новее кеша, поэтому остаётся пригодным. true не значит «обязательно что-то удалили»: он также означает, что менять было нечего.
В PHP 8.5.11 при настроенном file cache инвалидируется и его соответствующая запись. Возврат false возможен при выключенном/недоступном кеше; opcache.restrict_api тоже ограничивает вызов. Пользовательский URL не должен управлять путём сброса. Используйте перечень файлов своего релиза и исполняйте операцию в нужном SAPI/экземпляре; успешный CLI-вызов не доказывает обновление другого сервера.
Рядом по задаче: opcache_compile_file; opcache_reset; opcache_is_script_cached.
opcache_get_configurationПолучить настройки, версию и список исключений OPcache.
PHP 5.5+ · Zend OPcache
opcache_get_configuration(): array|falseПолучить настройки, версию и список исключений OPcache.
OPcache сохраняет подготовленный к исполнению PHP-код. При следующем запросе движок может взять готовые инструкции, но сами действия скрипта выполняются снова: SQL, HTTP-запросы, циклы и вывод не превращаются в готовый HTML-кеш. Экземпляр кеша связан с конкретным окружением PHP; консольный вызов не является удалённым управлением всеми PHP-FPM серверами.
| Часть вызова | Контракт |
|---|---|
| Аргументы | Нет. |
| Результат | Ассоциативный массив directives/version/blacklist либо false. |
| Ограничение | restrict_api может выдать warning и запретить доступ. |
Конфигурация отвечает «как кеш настроен», статус — «что с ним происходит сейчас». opcache_get_configuration возвращает массив directives, version и blacklist; объём свободной памяти и счётчики запросов получают другой функцией.
<?php
declare(strict_types=1);
$configuration = opcache_get_configuration();
if ($configuration === false) throw new RuntimeException('API недоступно');
$settings = $configuration['directives'];
echo $settings['opcache.enable'] ? "Кеш разрешён\n" : "Кеш отключён\n";
echo $settings['opcache.enable_cli'] ? "CLI разрешён\n" : "CLI отключён\n";
Ожидаемый результат
Кеш разрешён
CLI разрешён
Так настроен только учебный процесс. Серверный запрос может вернуть другую конфигурацию и даже другой набор параметров версии.
<?php
declare(strict_types=1);
$configuration = opcache_get_configuration();
if ($configuration === false) throw new RuntimeException('Нет конфигурации');
$automatic = $configuration['directives']['opcache.validate_timestamps'];
echo $automatic ? "Изменения файлов проверяются\n" : "Обновление требует действий deploy\n";
var_dump(is_array($configuration['blacklist']));
Ожидаемый результат
Изменения файлов проверяются
bool(true)
Это диагностика стратегии обновления, не универсальный выбор production-настроек. Даже при automatic=true важны интервал и другие кеши приложения.
При запрете opcache.restrict_api будет E_WARNING и данные не вернутся. Не выкладывайте весь массив в общедоступный endpoint: там могут быть пути и конфигурация сервера. Список полей зависит от версии/платформы; обращайтесь к известным ключам, а необязательные проверяйте. ini_set не умеет менять все перечисленные настройки: у INI_SYSTEM нужен перезапуск нужного процесса после изменения конфигурации.
Рядом по задаче: opcache_get_status; opcache_is_script_cached.
opcache_get_statusПосмотреть состояние памяти, статистику и при необходимости скрипты.
PHP 5.5+ · Zend OPcache
opcache_get_status(bool $include_scripts = true): array|falseПосмотреть состояние памяти, статистику и при необходимости скрипты.
OPcache сохраняет подготовленный к исполнению PHP-код. При следующем запросе движок может взять готовые инструкции, но сами действия скрипта выполняются снова: SQL, HTTP-запросы, циклы и вывод не превращаются в готовый HTML-кеш. Экземпляр кеша связан с конкретным окружением PHP; консольный вызов не является удалённым управлением всеми PHP-FPM серверами.
| Часть вызова | Контракт |
|---|---|
| include_scripts | true добавляет массив scripts; false ограничивается общими данными. |
| Результат | Статус in-memory экземпляра или false. Файловый кеш здесь не перечисляется. |
| Ошибки | restrict_api может вызвать E_WARNING и отказ. |
Для внутреннего мониторинга нужно видеть заполнение памяти, попадания и промахи, ожидающий restart. opcache_get_status(false) не включает большой перечень всех файлов и поэтому подходит для общего обзора. Данные относятся к текущему экземпляру памяти, не ко всем серверам и не к file cache.
<?php
declare(strict_types=1);
$status = opcache_get_status(false);
if ($status === false) throw new RuntimeException('Нет статуса памяти');
echo $status['opcache_enabled'] ? "Работает\n" : "Отключён\n";
echo array_key_exists('scripts', $status) ? "Со списком файлов\n" : "Без списка файлов\n";
echo $status['memory_usage']['free_memory'] > 0 ? "Есть свободная память\n" : "Память закончилась\n";
Ожидаемый результат
Работает
Без списка файлов
Есть свободная память
Это наблюдение собственной небольшой лаборатории. На сервере проверяют реальные числа и динамику, а не рассчитывают всегда получить те же фразы.
<?php
declare(strict_types=1);
$path = __DIR__ . '/calculation.php';
// Только наш учебный файл: исключаем защиту от совсем нового timestamp.
touch($path, time() - 60);
opcache_compile_file($path);
$status = opcache_get_status(true);
if ($status === false) throw new RuntimeException('Нет статуса');
$script = $status['scripts'][realpath($path)] ?? null;
echo is_array($script) ? "Учебный файл найден\n" : "Записи нет\n";
echo isset($script['revalidate']) ? "Есть время следующей проверки\n" : "Нет поля revalidate\n";
Ожидаемый результат
Учебный файл найден
Есть время следующей проверки
С PHP 8.3 revalidate — Unix timestamp следующей проверки времени изменения по revalidate_freq. Он не является временем исполнения бизнес-логики.
memory_usage различает занятую, свободную и wasted память; последняя относится к неиспользуемым областям после изменений, а не обязательно к утечке переменных приложения. opcache_statistics показывает hits/misses, количество скриптов и причины перезапусков. Hit rate оценивайте после прогрева и за сопоставимый период: один процент без нагрузки и числа запросов мало объясняет. restart_pending/restart_in_progress показывают состояние перехода; cache_full помогает найти ограничения. jit описывает отдельный механизм, а не само наличие OPcache.
Рядом по задаче: opcache_get_configuration; opcache_is_script_cached; opcache_reset.
opcache_resetЗапросить сброс всего кеша памяти текущего экземпляра.
PHP 5.5+ · Zend OPcache
opcache_reset(): boolЗапросить сброс всего кеша памяти текущего экземпляра.
OPcache сохраняет подготовленный к исполнению PHP-код. При следующем запросе движок может взять готовые инструкции, но сами действия скрипта выполняются снова: SQL, HTTP-запросы, циклы и вывод не превращаются в готовый HTML-кеш. Экземпляр кеша связан с конкретным окружением PHP; консольный вызов не является удалённым управлением всеми PHP-FPM серверами.
| Часть вызова | Контракт |
|---|---|
| Аргументы | Нет. |
| Результат | true при принятом сбросе, false при недоступности операции. |
| Граница | Не очищает файловый кеш и не заменяет restart процесса для preload. |
Полный reset нужен, когда развёртывание требует обновить весь экземпляр кеша памяти. Это административное действие с влиянием на следующие запросы, поэтому его не ставят в начало каждой страницы. PHP планирует перезапуск кеша, согласуя его с активной работой.
<?php
declare(strict_types=1);
if (PHP_SAPI !== 'cli' || !str_starts_with((string) ini_get('opcache.cache_id'), 'phpmanual-')) {
throw new RuntimeException('Пример запускается только в собственной CLI-лаборатории');
}
$accepted = opcache_reset();
echo $accepted ? "Запрос сброса принят\n" : "Запрос не принят\n";
Ожидаемый результат
Запрос сброса принят
У этой проверки есть собственный cache_id, не используемый другими процессами. true не обещает, что уже исполняющийся текущий запрос мгновенно переключился на новый исходный код.
<?php
declare(strict_types=1);
$path = __DIR__ . '/calculation.php';
// Только наш учебный файл: исключаем защиту от совсем нового timestamp.
touch($path, time() - 60);
if (PHP_SAPI !== 'cli' || !str_starts_with((string) ini_get('opcache.cache_id'), 'phpmanual-')) {
throw new RuntimeException('Только своя CLI-лаборатория');
}
opcache_compile_file($path);
opcache_reset();
var_dump(opcache_is_script_cached_in_file_cache($path));
Ожидаемый результат
bool(true)
Reset затронул память, но не удалил записанный файл второго уровня. Для одного изменённого пути существует opcache_invalidate; preloaded-код имеет свой процессный жизненный цикл.
Документация описывает false при недоступном/выключенном кеше и при невозможности сброса в текущем состоянии. Реализация PHP 8.5.11 планирует restart; успешный return не следует превращать в доказательство моментально пустого scripts. Не делайте публичный reset.php без контролируемого административного доступа. CLI, PHP-FPM, Apache, отдельные Windows cache_id и разные узлы имеют разные области кеширования — план обновления должен обращаться к нужному окружению.
Рядом по задаче: opcache_invalidate; opcache_get_status; opcache_is_script_cached_in_file_cache.
opcache_jit_blacklistИсключить функцию из дальнейшей tracing-JIT компиляции.
PHP 8.4+ · Zend OPcache
opcache_jit_blacklist(Closure $closure): voidИсключить функцию из дальнейшей tracing-JIT компиляции.
OPcache сохраняет подготовленный к исполнению PHP-код. При следующем запросе движок может взять готовые инструкции, но сами действия скрипта выполняются снова: SQL, HTTP-запросы, циклы и вывод не превращаются в готовый HTML-кеш. Экземпляр кеша связан с конкретным окружением PHP; консольный вызов не является удалённым управлением всеми PHP-FPM серверами.
| Часть вызова | Контракт |
|---|---|
| closure | Конкретная функция как first-class callable или анонимная Closure. |
| Результат | void. Функция продолжает исполняться обычным способом. |
| Ограничение | Не отменяет ранее скомпилированные участки; PHP 8.4+. |
Иногда при диагностике JIT нужно исключить одну функцию из последующей трассирующей компиляции, оставив обычное исполнение PHP. opcache_jit_blacklist получает Closure, представляющий конкретную функцию. Это не запрет вызывать функцию и не защита от опасного кода.
<?php
declare(strict_types=1);
function addDelivery(int $items, int $delivery): int { return $items + $delivery; }
opcache_jit_blacklist(addDelivery(...));
echo addDelivery(1000, 200), "\n";
Ожидаемый результат
1200
addDelivery(...) без аргументов здесь — синтаксис first-class callable, создающий Closure. Сам вызов с числами находится на следующей строке. JIT в нашей лаборатории выключен: проверены доступность API и обычное исполнение, не машинная трасса.
<?php
declare(strict_types=1);
$normalize = static fn(int $value): int => max(0, $value);
opcache_jit_blacklist($normalize);
echo $normalize(-4), "\n";
Ожидаемый результат
0
Анонимная функция уже является Closure. Исключается именно она; остальные вычисления программы не становятся частью этого запрета. Возвращаемого значения у blacklist нет.
API добавлен в PHP 8.4 и относится к tracing JIT. Уже скомпилированные участки он не отменяет, поэтому настройку применяют до первого выполнения нужной функции. Для строкового имени потребуется получить Closure, а не передать строку напрямую. Blacklist — инструмент локализации проблем компилятора, не универсальная оптимизация приложения. Чтобы утверждать эффект на трассы, нужен отдельный запуск с включённым поддерживаемым JIT и его диагностикой.
Рядом по задаче: opcache_get_status; opcache_get_configuration.
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


