Миграция с Yii1 на Yii2: стратегия без остановки проекта
Yii1 не обновлялся с 2015 года, а Yii2 — не патч, а другой фреймворк. Разбираем стратегии перехода: переписать сразу, мигрировать частями или жить на двух ядрах, и чем платит каждая.

Yii 1.1 официально дошёл до конца поддержки: последний релиз ветки вышел в 2015 году, а безопасностные заплатки прекратились ещё раньше. Если у вас на нём крутится живой проект — интернет-магазин, CRM, портал — вы сидите на коде, который зависит от PHP 5.x-совместимых практик и не запустится нормально на PHP 8. Миграция на Yii2 — это не апгрейд по номеру версии, а переезд на другой фреймворк с тем же именем. Ниже — стратегии перехода и цена каждой, без иллюзии, что есть кнопка «обновить».
Почему это не апгрейд, а переписывание
Yii1 и Yii2 несовместимы на уровне почти всего, что вы трогаете каждый день. Меняется структура namespace, механизм автозагрузки, синтаксис ActiveRecord, работа с виджетами, конфигурация приложения. Код из Yii1 не запустится под Yii2 ни строкой.
- Namespace и автозагрузка. Yii1 работал через
Yii::import()и пути. Yii2 построен на PSR-совместимой автозагрузке через Composer и полноценные namespace. - ActiveRecord. В Yii1 связи описывались в методе
relations()массивом. В Yii2 каждая связь — отдельный метод, возвращающийActiveQueryчерезhasOne()/hasMany(). - Компоненты и DI. Yii2 использует контейнер зависимостей и конфигурацию компонентов иначе, чем
CApplicationв Yii1. - Виджеты и представления. Классы вроде
CActiveFormзаменены наyii\widgets\ActiveFormс другим API.
Практический вывод: не рассчитывайте на автоматический конвертер. Официальный раздел руководства «Upgrading from Version 1.1» — это карта различий, а не скрипт миграции.
Yii2 — не следующая версия Yii1, а самостоятельный фреймворк, который унаследовал философию, но не код. Планируйте бюджет как на новый проект с готовой бизнес-логикой, а не как на обновление.
Три стратегии перехода
Выбор зависит от одного: можете ли вы позволить себе заморозить разработку фич на время переезда. Ответ обычно «нет», и это отсекает самый простой путь.
Стратегия 1 — big bang: переписать целиком и выкатить разом
Вы поднимаете новый проект на Yii2, переносите модели, контроллеры и представления, а в день X переключаете трафик. Старый код удаляется.
Работает для небольших проектов — до нескольких десятков контроллеров, где команда способна пройти переезд за спринт-два. На крупной системе это ловушка: пока вы переписываете, продукт стоит, а бизнес продолжает требовать фичи, которые придётся делать дважды.
Стратегия 2 — strangler: два приложения за одним доменом
Yii1 и Yii2 живут параллельно, а веб-сервер маршрутизирует запросы: часть URL уходит в старое приложение, часть — в новое. Вы переносите функциональность по кускам, и с каждым куском доля Yii2 растёт, а Yii1 «удушается» (отсюда strangler — паттерн удушающего фасада).
Маршрутизацию делает Nginx по префиксам путей. Схематично:
# Новые разделы — в Yii2 (перенесённые), корень пока в Yii1
location /account/ {
root /var/www/yii2/web;
try_files $uri /account/index.php$is_args$args;
}
location / {
root /var/www/yii1/web;
try_files $uri /index.php$is_args$args;
}
Главная сложность здесь — общая сессия и авторизация. Два приложения должны понимать одну и ту же сессию пользователя, иначе при переходе между разделами человека будет выкидывать на логин. Решается общим хранилищем сессий (например, в базе или Redis) с одинаковым именем cookie и совместимым форматом. Формат сериализации данных сессии в Yii1 и Yii2 различается, поэтому саму структуру данных придётся согласовывать вручную.
Стратегия 3 — модели вперёд, слой доступа общий
Промежуточный вариант: вы держите единую базу данных, а бизнес-логику переносите в Yii2 постепенно, оставляя старый фронт на Yii1 до последнего. Подходит, если самое ценное и хрупкое у вас — слой данных, а представления простые.
Сравнение стратегий
| Критерий | Big bang | Strangler | Модели вперёд |
|---|---|---|---|
| Заморозка фич | Полная, на весь срок | Нет | Частичная |
| Риск на день X | Высокий: всё сразу | Низкий: по кускам | Средний |
| Сложность инфраструктуры | Низкая | Высокая (2 приложения, общая сессия) | Средняя |
| Срок до первого результата | Долго (всё или ничего) | Быстро (первый раздел) | Средне |
| Кому подходит | Малые проекты | Крупные живые системы | Data-heavy проекты |
Что переносить в первую очередь
Независимо от стратегии, порядок переноса влияет на риск. Начинайте с того, что даёт быструю обратную связь и меньше всего завязано на остальное.
- Схема БД и модели ActiveRecord. База остаётся одна, меняется только код доступа. Перепишите связи из
relations()в методы-запросы Yii2 и покройте их тестами до переноса контроллеров. - Авторизация и сессии. Если выбрали strangler — это критический узел, решайте его раньше фич.
- Изолированные разделы. Личный кабинет, отдельный модуль отчётов — то, что можно вырезать и перенести без каскада зависимостей.
- Ядро с максимальными связями — в последнюю очередь. Корзина, оформление заказа, платежи переносятся, когда вокруг уже стоит рабочий Yii2.
Разница в ActiveRecord: на что закладываться
Самый частый источник тихих багов при миграции — связи. В Yii1 они описаны декларативно:
// Yii1: CActiveRecord
public function relations()
{
return array(
'orders' => array(self::HAS_MANY, 'Order', 'customer_id'),
);
}
В Yii2 (ветка 2.0.x) та же связь — отдельный метод:
<?php
// Yii2 2.0.x: yii\db\ActiveRecord
namespace app\models;
use yii\db\ActiveRecord;
class Customer extends ActiveRecord
{
// Связь "один клиент — много заказов"
public function getOrders()
{
return $this->hasMany(Order::class, ['customer_id' => 'id']);
}
}
Обращение тоже меняется: в Yii1 вы читали $customer->orders, в Yii2 доступ к $customer->orders работает так же за счёт магии геттера, но $customer->getOrders() вернёт объект запроса, а не данные. Это тонкость, на которой спотыкаются при переносе: не путайте свойство-связь и метод-запрос.
Где переезд ломается на практике
- Общая сессия. Разный формат данных сессии между версиями — пользователей выкидывает на логин при переходе между разделами. Проверяйте на реальном сценарии «залогинился в старом разделе, перешёл в новый».
- Расширения без версии под Yii2. Часть Yii1-экстеншенов заброшена. Заранее составьте список зависимостей и проверьте, есть ли аналоги в Packagist под Yii2, иначе функционал придётся писать самому.
- PHP-версия. Yii1 не рассчитан на PHP 8. Если вы держите два приложения на одном сервере, им может понадобиться разное окружение PHP — проще разнести по разным PHP-FPM пулам.
- URL и SEO. При маршрутизации по префиксам легко случайно изменить структуру URL. Сохраняйте адреса перенесённых разделов один в один или ставьте 301-редиректы.
Что делать дальше
Первый практический шаг — инвентаризация: выпишите все контроллеры, модули и сторонние расширения, отметьте, у каких есть Yii2-аналог. Это покажет реальный объём работы честнее любой оценки «на глаз». Затем поднимите пустое приложение Yii2 через Composer рядом со старым и перенесите один изолированный раздел целиком — до продакшена, с тестами и мониторингом. По одному куску вы поймёте свою скорость и уже осмысленно выберете между strangler и big bang. Метрика, за которой стоит следить в проде во время переезда, — доля запросов, уходящих в Yii2, и число редиректов на логин: рост второго означает, что общая сессия настроена неверно.
Проверка грамотности: Орфография, пунктуация, стиль — с объяснением каждой правки
Спросить за 10 ₽Источники: Yii2 Guide — Upgrading from Version 1.1, Yii Framework — официальная документация
Частые вопросы
Есть ли автоматический конвертер кода из Yii1 в Yii2?
Можно ли запустить Yii1 и Yii2 одновременно на одном проекте?
А если у меня Yii 1.1, а не какая-то более старая версия — проще?
Что делать, если у меня Yii2 другой версии, чем в примерах?
Что делать, если нужного расширения нет под Yii2?
Сколько времени занимает миграция?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.