← к кейсам

Миграция биллинга с Zend Framework на Laminas

2021
PHP Laminas Zend Framework PostgreSQL Docker

Предыстория

Zend Framework официально прекратил поддержку в конце 2019 года и перешёл в Laminas Project. Для большинства компонентов это была простая замена неймспейса: Zend\Laminas\. Но в нашем случае биллинговая система работала на продакшне круглосуточно, а код содержал несколько самописных расширений под конкретные версии Zend-компонентов.

Перейти «одним коммитом» было нельзя — слишком большой риск.

Стратегия

Разбил миграцию на три фазы, каждую из которых можно откатить независимо.

Фаза 1: Зависимости

Обновил composer.json: заменил zendframework/* пакеты на laminas/* эквиваленты. Laminas предоставляет пакет совместимости laminas/laminas-zendframework-bridge, который на уровне автолоадера алиасит старые неймспейсы на новые. Это позволило запустить систему без изменения ни одной строки PHP-кода.

Развернул окружение в Docker, прогнал функциональные тесты — всё прошло. Выкатил на стейдж.

Фаза 2: Замена неймспейсов

Написал скрипт на базе rector/rector, который автоматически переименовал Zend\Laminas\ по всей кодовой базе (~18 000 строк). Прогнал тесты после каждого модуля, а не после всего сразу.

Трёх мест автоматическая замена не решила: там были строковые имена классов в конфигах и один рефлексивный вызов. Правил руками.

Фаза 3: Удаление моста совместимости

После того как неймспейсы заменены и всё работает, убрал laminas-zendframework-bridge из зависимостей. Это финальная точка — теперь код зависит только от Laminas.

Деплой без даунтайма

Биллинг не мог останавливаться. Использовали стандартную схему: сначала выкатили фазу 1 (только зависимости) с мостом совместимости — ничего не поменялось для пользователей. Потом поэтапно фазы 2 и 3.

В каждой точке был зафиксирован снепшот базы данных и образ Docker — для быстрого отката. Фактически откатываться не пришлось ни разу.

Что узнал

Ключевой момент — не пытаться сделать всё за один раз. Мост совместимости даёт время, чтобы прогнать тесты и убедиться, что система работает на новой основе, не меняя при этом продуктовый код.

Rector значительно ускоряет механическую работу по переименованию, но не заменяет понимание архитектуры — нужно знать, где строки с именами классов живут в конфигах.

Итог

Миграция заняла около трёх недель в фоновом режиме. Система получила актуальную кодовую базу, поддерживаемые зависимости и возможность обновляться дальше. Без единой минуты даунтайма.