Міграція

Цей посібник допоможе перенести наявний PHP-застосунок на OxPHP. Почніть із розділу про те, що ви використовуєте зараз, — nginx + PHP-FPM або FrankenPHP і RoadRunner, — а перш ніж остаточно вирішити переходити, прочитайте розділ Що не переноситься.

З nginx + PHP-FPM

Більшість застосунків переходять без змін у коді. Типовий режим виконує кожен запит із чистого стану PHP — це той самий життєвий цикл, що й у PHP-FPM, — тож уся робота зводиться до перенесення конфігурації. Приклади розгортання — це готові рецепти для Laravel, Symfony, WordPress, Drupal, Magento та інших.

1. Оберіть режим маршрутизації, що відповідає вашому try_files

nginx OxPHP
try_files $uri /index.php?$query_string (Laravel, Symfony, Yii) ENTRY_FILE=index.php (Framework)
try_files $uri $uri/ /index.php з кількома точками входу PHP (WordPress, OpenCart) ENTRY_FILE не задано (Traditional)
try_files $uri /index.html для односторінкового застосунку ENTRY_FILE=index.html (SPA)

2. Зберіть образ

Почніть із дворядкового Dockerfile зі Швидкого старту. Розширення мають бути зібрані для потокобезпечного PHP — в етапі php:*-zts-alpine з тією самою мінорною версією PHP, що й в образі OxPHP; див. Встановлення розширень PHP у продакшні.

Warning

Переконайтеся, що кожне PECL-розширення, яке ви використовуєте, підтримує ZTS. OxPHP працює лише з потокобезпечним PHP, тож розширення без підтримки ZTS не вдасться завантажити.

3. Перенесіть конфігурацію

Образ не завантажує жодного php.ini. Тримайте свої налаштування PHP (memory_limit, upload_max_filesize, OPcache, …) у власному файлі будь-де в проєкті, наприклад docker/php.ini, і скопіюйте його в каталог конфігурації PHP в образі. Цей каталог — шлях усередині контейнера, а не у вашому проєкті:

Dockerfile
FROM ghcr.io/oxphp/oxphp:0.13.0 COPY docker/php.ini /usr/local/etc/php/conf.d/zz-app.ini COPY --chown=www-data:www-data . /var/www/html/public

PHP читає всі файли .ini у цьому каталозі в алфавітному порядку, і діє останнє значення, тож завдяки префіксу zz- ваш файл застосовується після власних файлів образу. Можна також змонтувати файл як том; див. Налаштування PHP.

Решта відповідає змінним середовища:

nginx / PHP-FPM OxPHP
listen 443 ssl, ssl_certificate TLS_CERT, TLS_KEY, TLS_MIN_VERSION; див. TLS
pm = static / pm = dynamic, pm.max_children PHP_WORKERS=N / PHP_WORKERS=MIN:MAX
php_admin_value[...], php.ini ваш власний файл .ini, скопійований в образі до /usr/local/etc/php/conf.d/ (див. вище)
gzip on, brotli on увімкнено типово, налаштовується через COMPRESSION_ENCODINGS; див. Стиснення
expires 30d для статичних файлів STATIC_MAX_AGE (типово 30d)
limit_req RATE_LIMIT, RATE_WINDOW_SECONDS (фіксоване вікно для кожної IP-адреси); див. Обмеження частоти запитів
set_real_ip_from, real_ip_header TRUSTED_PROXIES; див. Довірені проксі
error_page 404 /404.html ERROR_PAGES_DIR із файлами {status}.html; див. Сторінки помилок
access_log ACCESS_LOG=all або error (рядки JSON); див. Журнал доступу
location ~ ^/uploads/.*\.php$ { deny all; } PHP_DENY_PATHS=/uploads/**; див. Список заборони виконання PHP
pm.status_path, ping.path INTERNAL_ADDR з /health і /metrics; див. Перевірки стану
fastcgi_finish_request() oxphp_finish_request(); див. Рання відповідь

4. Перевірте відмінності в поведінці

  • max_execution_time рахує реальний час. У PHP-FPM час очікування бази даних або HTTP-виклику не зараховується, а в потокобезпечному PHP — зараховується. Повільний ендпоінт, який раніше ніколи не досягав ліміту, може почати повертати 504. Див. Тайм-аути.
  • php_sapi_name() повертає cli-server. Коду, що розгалужується за значенням fpm-fcgi, потрібна інша перевірка: function_exists('oxphp_request_id').
  • Кілька ключів $_SERVER відрізняються. SERVER_ADDR, PATH_TRANSLATED і REDIRECT_STATUS не встановлюються, а PHP_AUTH_USER / PHP_AUTH_PW не видобуваються; натомість читайте HTTP_AUTHORIZATION. Див. Відмінності від PHP-FPM.
  • Вбудовування у фрейми типово обмежене. Відповіді містять X-Frame-Options: SAMEORIGIN і відповідну політику frame-ancestors. Задайте FRAME_OPTIONS=off, якщо керуєте вбудовуванням в інший спосіб або вбудовуєте застосунок у сторінки іншого походження; див. Захист від клікджекінгу.

5. Розгортайте поруч зі старим стеком

Запустіть OxPHP поруч із nginx + PHP-FPM, спрямуйте на нього частину трафіку через наявний балансувальник навантаження, використовуйте /health/readiness для проб і порівняйте частоту помилок і затримку за /metrics, перш ніж переносити решту.

6. Вмикайте режим воркерів наостанок

Спершу виконайте міграцію в типовому режимі. Потім задайте WORKER_MODE_ENABLED=true і вкажіть в ENTRY_FILE скрипт воркера. Стан у статичних властивостях і довготривалі з’єднання відтепер зберігаються між запитами, тож перш ніж вмикати цей режим, прочитайте розділ Що скидається і що зберігається.

З FrankenPHP або RoadRunner

Скрипти воркерів зберігають свою форму: спершу одноразова ініціалізація, потім обслуговування запитів. Замініть цикл frankenphp_handle_request() одним викликом oxphp_worker($handler). OxPHP сам виконує цикл і викликає обробник для кожного запиту; усередині обробника читайте запит із суперглобальних змінних або через oxphp_http_request(). Цикл PSR-7 waitRequest() / respond() з RoadRunner не має відповідника: перенесіть обробник застосунку в той самий колбек. Див. oxphp_worker() і Режим воркерів.

Приберіть лічильник MAX_REQUESTS

Відповідника немає, і він вам не потрібен: воркер не розрахований на перезапуск кожні N запитів, а такий перезапуск лише приховує витік пам’яті. Якщо ви його підозрюєте, краще відстежуйте:

  • Будуйте графік oxphp_worker_memory_bytes для кожного воркера і стежте, чи не зростає він невпинно.
  • Задайте WORKER_MAX_MEMORY_MIB як запобіжник. Воркер, що перевищив ліміт, замінюється раніше, ніж контейнерові забракне пам’яті, і кожен такий перезапуск враховується в oxphp_worker_recycles_by_reason_total{reason="max_memory"}.
  • Цей ліміт вимірює лише власну купу PHP. Якщо стек активно використовує розширення, порівнюйте Worker::current()->rss() із власним порогом і викликайте Worker::scheduleExit().

Що не переноситься

  • OxPHP не підтримує зворотне проксіювання чи upstream-сервери: немає ні proxy_pass, ні WebSocket-сервера. Якщо nginx також стоїть перед іншими сервісами, залиште проксі перед OxPHP для цих маршрутів.
  • Екземпляр має один порт і один протокол. Він обслуговує або звичайний HTTP, або HTTPS, але не обидва, тож для перенаправлення з порту 80 на HTTPS потрібен проксі або другий екземпляр. Сертифікат читається під час запуску, тож після його оновлення потрібен перезапуск; див. TLS.
  • HTTP/3 і 103 Early Hints поки що недоступні; див. дорожню карту.
  • OxPHP працює лише в Linux і поширюється як образ Docker. Пакетів apt чи brew немає. Підтримуються PHP 8.4 і 8.5.

Промпти для вашого агента

Ці промпти розраховані на агента з підключеним MCP-сервером документації OxPHP — потрібні сторінки він прочитає сам.

prompt
Перенеси цей застосунок із nginx і PHP-FPM на OxPHP. Прочитай сторінку `getting-started/migration` через MCP-сервер документації OxPHP. Перетвори серверні блоки nginx, налаштування пулу PHP-FPM і перевизначення php.ini з цього репозиторію на Dockerfile для OxPHP і змінні середовища, обери режим маршрутизації за правилами `try_files` і перелічи всі відмінності в поведінці та непідтримувані можливості, які стосуються цього коду, вказавши для кожної файл, якого вона стосується.
prompt
Перенеси воркер FrankenPHP або RoadRunner із цього репозиторію на OxPHP. Прочитай сторінку `getting-started/migration` через MCP-сервер документації OxPHP. Перепиши скрипт воркера навколо одного виклику `oxphp_worker()`, прибери будь-який лічильник, що перезапускає воркер кожні N запитів, і скажи, яку метрику та який ліміт пам’яті налаштувати натомість.

Що далі