Обновление с Yii 1.1

Между версиями 1.1 и 2.0 существует много различий, так как Yii был полностью переписан для версии 2.0. Таким образом, обновление с версии 1.1 не является таким же тривиальным как обновление между минорными версиями. В данном руководстве приведены основные различия между двумя версиями.

Если прежде вы не использовали Yii 1.1, вы можете сразу перейти к разделу «Начало работы».

Также учтите, что в Yii 2.0 гораздо больше новых возможностей, чем описано далее. Настоятельно рекомендуется, изучить всё руководство. Вполне возможно, что то, что раньше приходилось разрабатывать самостоятельно теперь является частью фреймворка.

Установка

Yii 2.0 широко использует Composer, который является основным менеджером зависимостей для PHP. Установка как фреймворка, так и расширений, осуществляется через Composer. Подробно о установке Yii 2.0 вы можете узнать из раздела «Установка Yii». О том, как создавать расширения для Yii 2.0 или адаптировать уже имеющиеся расширения от версии 1.1, вы можете узнать из раздела «Создание расширений».

Требования PHP

Для работы Yii 2.0 необходим PHP 5.4 или выше. Данная версия включает большое количество улучшений по сравнению с версией 5.2, которая использовалась Yii 1.1. Таким образом, существует много различий в языке, которые вы должны принимать во внимание:

  • Пространства имён;
  • Анонимные функции;
  • Использование короткого синтаксиса для массивов: [...элементы...] вместо array(...элементы...);
  • Использование короткого echo <?= для вывода в файлах представлений. С версии PHP 5.4 данную возможность можно использовать не опасаясь;
  • Классы и интерфейсы SPL;
  • Позднее статическое связывание (LSB);
  • Классы для дат и времени;
  • Трейты;
  • Интернационализация (intl); Yii 2.0 использует расширение PHP intl для различного функционала интернационализации.

Пространство имен

Одним из основных изменений в Yii 2.0 является использование пространств имён. Почти каждый класс фреймворка находится в пространстве имён, например, yii\web\Request. Префикс "С" в именах классов больше не используется. Имена классов соответствуют структуре директорий. Например, yii\web\Request указывает, что соответствующий класс находится в файле web/Request.php в директории фреймворка.

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

Компонент и объект

В Yii 2.0 класс CComponent из версии 1.1 был разделён на два класса: [[yii\base\Object]] и [[yii\base\Component]]. Класс [[yii\base\Object|Object]] является простым базовым классом, который позволяет использовать геттеры и сеттеры для свойств. Класс [[yii\base\Component|Component]] наследуется от класса [[yii\base\Object|Object]] и поддерживает события и поведения.

Если вашему классу не нужны события или поведения, вы можете использовать [[yii\base\Object|Object]] в качестве базового класса. В основном это относится к классам, представляющим собой базовые структуры данных.

Конфигурация объекта

Класс [[yii\base\Object|Object]] предоставляет единый способ конфигурирования объектов. Любой дочерний класс [[yii\base\Object|Object]] может определить конструктор (если нужно) как показано ниже. Это позволит конфигурировать его универсально:

class MyClass extends \yii\base\Object
{
    public function __construct($param1, $param2, $config = [])
    {
        // ... инициализация до того, как конфигурация будет применена
 
        parent::__construct($config);
    }
 
    public function init()
    {
        parent::init();
 
        // ... инициализация после того, как конфигурация была применена
    }
}

В примере выше, последний параметр конструктора должен быть массивом конфигурации, который содержит пары в формате ключ-значение для инициализации свойств объекта. Вы можете переопределить метод [[yii\base\Object::init()|init()]] для инициализации объекта после того, как конфигурация была применена к нему.

Следуя этому соглашению, вы сможете создавать и конфигурировать новые объекты с помощью массива конфигурации:

$object = Yii::createObject([
    'class' => 'MyClass',
    'property1' => 'abc',
    'property2' => 'cde',
], [$param1, $param2]);

Более подробная информация о конфигурации представлена в разделе «Настройки».

События

В Yii 1, события создавались с помощью объявления метода on (например, onBeforeSave). В Yii2 вы можете использовать любое имя события. Вызывать события можно при помощи метода [[yii\base\Component::trigger()|trigger()]].

$event = new \yii\base\Event;
$component->trigger($eventName, $event);

Для прикрепления обработчика события используйте метод [[yii\base\Component::on()|on()]].

$component->on($eventName, $handler);
// убираем обработчик
// $component->off($eventName, $handler);

Есть и другие улучшения по части событий, подробно описанные в разделе «События».

Псевдонимы пути

В Yii 2.0 псевдонимы используются более широко и применяются как к путям в файловой системе, так и к URL. Теперь, для того, чтобы отличать псевдонимы от обычных путей и URL, требуется, чтобы имя псевдонима начиналось с символа @. Например, псевдоним @yii соответствует директории, в которую установлен Yii. Псевдонимы пути используются во многих местах. Например, значение свойства [[yii\caching\FileCache::cachePath]] может быть как псевдонимом пути так и обычным путём к папке.

Псевдонимы пути тесно связаны с пространством имён классов. Рекомендуется определять псевдоним пути для каждого корневого пространства имён, что позволяет использовать загрузчик классов Yii без какой-либо дополнительной настройки. Например, так как @yii соответствует директории, в которую установлен фреймворк, класс yii\web\Request может быть загружен автоматически. Если вы используете сторонние библиотеки, например, из Zend Framework, вы можете определить псевдоним пути @Zend как директорию, в которую установлен этот фреймворк. После этого Yii будет способен автоматически загружать любой класс Zend Framework.

Подробнее о псевдонимах пути можно узнать из раздела «Псевдонимы пути».

Представления

Одним из основных изменений в Yii 2 является то, что специальная переменная $this в представлении, больше не соответствует текущему контроллеру или виджету. Вместо этого, $this теперь соответствует объекту представления, новой возможности введённой в версии 2.0. Объект представления имеет тип [[yii\web\View]], который представляет собой часть view в шаблоне проектирования MVC. Если вы хотите получить доступ к контроллеру или виджету, используйте выражение $this->context.

Для рендеринга частичных представлений теперь используется метод $this->render(), а не $this->renderPartial(). Результат вызова метода render теперь должен быть выведен напрямую, так как render возвращает результат рендеринга, а не отображает его сразу:

echo $this->render('_item', ['item' => $item]);

Кроме использования PHP в качестве основного шаблонизатора, Yii 2.0 также предоставляет официальные расширения для двух популярных шаблонизаторов: Smarty и Twig. Шаблонизатор Prado больше не поддерживается. Для использования данных шаблонизаторов необходимо настроить компонент приложения view задав свойство [[yii\base\View::$renderers|View::$renderers]]. Подробнее об этом можно прочитать в разделе «Шаблонизаторы».

Модели

Yii 2.0 использует в качестве базового класса для моделей [[yii\base\Model]], аналогичный классу CModel в версии 1.1. Класс CFormModel удалён. Вместо него для создания модели формы в Yii 2.0 вы должны напрямую наследоваться от [[yii\base\Model]].

Появился новый метод [[yii\base\Model::scenarios()|scenarios()]] для объявления поддерживаемых сценариев, и для обозначения в каком сценарии атрибуты должны проверяться, считаться безопасными и т.п. Например,

public function scenarios()
{
    return [
        'backend' => ['email', 'role'],
        'frontend' => ['email', '!role'],
    ];
}

В примере выше, объявлено два сценария: backend и frontend. Для backend сценария, оба атрибута email и role являются безопасными, и могут быть массово присвоены. Для сценария frontend, атрибут email может быть массово присвоен, а атрибут role нет. Оба атрибута email и role должны быть проверены с помощью правил валидации.

Метод [[yii\base\Model::rules()|rules()]] по-прежнему используется для объявления правил валидации. Обратите внимание, что в связи с появлением нового метода [[yii\base\Model::scenarios()|scenarios()]], больше не поддерживается валидатор unsafe.

В большинстве случаев вам не нужно переопределять метод [[yii\base\Model::scenarios()|scenarios()]], если метод [[yii\base\Model::rules()|rules()]] полностью указывает все существующие сценарии, и если нет надобности в объявлении атрибутов небезопасными.

Более детальная информация представлена в разделе «Модели».

Контроллеры

В качестве базового класса для контроллеров в Yii 2.0 используется [[yii\web\Controller]], аналогичный CController в Yii 1.1. Базовым классом для всех действий является [[yii\base\Action]].

Одним из основных изменений является то, что действие контроллера теперь должно вернуть результат вместо того, чтобы напрямую выводить его:

public function actionView($id)
{
    $model = \app\models\Post::findOne($id);
    if ($model) {
        return $this->render('view', ['model' => $model]);
    } else {
        throw new \yii\web\NotFoundHttpException;
    }
}

Более детальная информация представлена в разделе «Контроллеры».

Виджеты

В Yii 2.0 класс [[yii\base\Widget]] используется в качестве базового класса для виджетов, аналогично CWidget в Yii 1.1.

Для лучшей поддержки фреймворка в IDE, Yii 2.0 использует новый синтаксис для виджетов. Новые статические методы [[yii\base\Widget::begin()|begin()]], [[yii\base\Widget::end()|end()]], и [[yii\base\Widget::widget()|widget()]] используются следующим образом:

use yii\widgets\Menu;
use yii\widgets\ActiveForm;
 
// Обратите внимание что вы должны выводить результат
echo Menu::widget(['items' => $items]);
 
// Указываем массив для конфигурации свойств объекта
$form = ActiveForm::begin([
    'options' => ['class' => 'form-horizontal'],
    'fieldConfig' => ['inputOptions' => ['class' => 'input-xlarge']],
]);
... поля формы ...
ActiveForm::end();

Более детальная информация представлена в разделе «Виджеты».

Темы

В Yii 2.0 темы работают совершенно по-другому. Теперь они основаны на механизме сопоставления путей исходного файла представления с темизированным файлом. Например, если используется сопоставление путей ['/web/views' => '/web/themes/basic'], то темизированная версия файла представления /web/views/site/index.php будет находится в /web/themes/basic/site/index.php. По этой причине темы могут быть применены к любому файлу представления, даже к представлению, отрендеренному внутри контекста контроллера или виджета. Также, больше не существует компонента CThemeManager. Вместо этого, theme является конфигурируемым свойством компонента приложения view.

Более детальная информация представлена в разделе «Темизация».

Консольные приложения

Консольные приложения теперь организованы как контроллеры, аналогично веб приложениям. Консольные контроллеры должны быть унаследованы от класса [[yii\console\Controller]], аналогичного CConsoleCommand в версии 1.1.

Для выполнения консольной команды, используйте yii <маршрут>, где <маршрут> это маршрут контроллера (например, sitemap/index). Дополнительные анонимные аргументы будут переданы в качестве параметров соответствующему действию контроллера, в то время как именованные аргументы будут переданы в соответствие с объявлениями в [[yii\console\Controller::options()]].

Yii 2.0 поддерживает автоматическую генерацию справочной информации из блоков комментариев.

Более детальная информация представлена в разделе «Консольные команды».

I18N

В Yii 2.0 встроенные форматтеры времени и чисел были убраны в пользу PECL расширения PHP intl.

Перевод сообщений теперь осуществляется через компонент приложения i18n. Данный компонент управляет множеством исходных хранилищ сообщений, что позволяет вам использовать разные хранилища для исходных сообщений в зависимости от категории сообщения.

Более детальная информация представлена в разделе «Интернационализация».

Фильтры действий

Теперь фильтры действий реализованы через поведения. Для определения нового фильтра Вам нужно наследовать класс yii\base\ActionFilter. Для использования фильтра, Вам нужно привязать его класс к контроллеру как поведение. Например, для использования фильтра yii\filters\AccessControl, в Вашем контроллере должен быть следующий код:

public function behaviors()
{
    return [
        'access' => [
            'class' => 'yii\filters\AccessControl',
            'rules' => [
                ['allow' => true, 'actions' => ['admin'], 'roles' => ['@']],
            ],
        ],
    ];
}

Подробнее о фильтрах действий смотрите в разделе Контроллер.

Ресурсы

В Yii 2.0 вводится новая концепция под названием комплект ресурсов. Это похоже на пакеты скриптов (управляемые CClientScript) в версии 1.1, но с улучшенной поддержкой. Комплект ресурсов это набор файлов ресурсов (таких как JavaScript файлы, CSS файлы, файлы изображений, и т.д.) собранные в одной папке. Каждый комплект ресурсов - это расширение класса yii\web\AssetBundle. Регистрируя комплект ресурсов с помощью yii\web\AssetBundle::register(), Вы делаете ресурсы этого комплекта доступными через веб, и текущая страница будет автоматически содержать ссылки на файлы JavaScript и CSS содержащиеся в этом комплекте.

Подробнее о ресурсах смотрите в разделе Управление ресурсами.

Статические хелперы

В Yii 2.0 представлено множество часто используемых вспомогательных статических классов, таких как Html, ArrayHelper, StringHelper, FileHelper, Json, Security. Эти классы разработаны легко расширяемыми. Заметьте, что обычно статические классы трудно расширяемы, так как используется постоянная ссылка на имя класса. Но в Yii 2.0 введена карта классов (с помощью Yii::$classMap) что бы обойти эту сложность.

ActiveForm

В Yii 2.0 введено понятие поле при построении форм с помощью yii\widgets\ActiveForm. Поле - это контейнер состоящий из метки, поля ввода, сообщение ошибки, и/или текст подсказки. Оно представлено в виде объекта ActiveField. Используя поля, вы можете создавать формы более аккуратно, чем раньше:

<?php $form = yii\widgets\ActiveForm::begin(); ?>
    <?= $form->field($model, 'username') ?>
    <?= $form->field($model, 'password')->passwordInput() ?>
    <div class="form-group">
        <?= Html::submitButton('Login') ?>
    </div>
<?php yii\widgets\ActiveForm::end(); ?>

Построитель запросов

В версии 1.1, построение запросов разбросано по нескольким классам, включая CDbCommand, CDbCriteria, и CDbCommandBuilder. В Yii 2.0 используется объект Query для представления запроса к базе данных и QueryBuilder для создания SQL запроса из объектов запросов. Например:

$query = new \yii\db\Query();
$query->select('id, name')
      ->from('user')
      ->limit(10);
 
$command = $query->createCommand();
$sql = $command->sql;
$rows = $command->queryAll();

Лучше всего, такие методы построения запросов могут быть использованы совместно с ActiveRecord, как описано в следующем подразделе.

ActiveRecord

В Yii 2.0 ActiveRecord претерпел значительные изменения. Наиболее важным является введение реляционных запросов ActiveRecord. В версии 1.1, Вам нужно было объявлять отношения в методе relations(). В версии 2.0, это делается с помощью методов геттеров которые возвращают объект ActiveQuery. Например, следующий метод объявляет отношение "orders":

class Customer extends \yii\db\ActiveRecord
{
    public function getOrders()
    {
        return $this->hasMany('Order', ['customer_id' => 'id']);
    }
}

Вы можете использовать $customer->orders что бы получить заказы покупателя. Вы также можете использовать $customer->getOrders()->andWhere('status=1')->all() для выполнения реляционного запроса "на лету" с измененными условиями. В Yii 2.0 загрузка реляционных записей в жадном режиме отличается от версии 1.1. В частности, в версии 1.1 будет использован запрос JOIN получения основных и связанных записей; тогда как в 2.0, будет выполнено два SQL запроса без использования JOIN: первый запрос вернет основные записи, а второй вернет связанные записи, отфильтрованные по первичным ключам основных записей.

В Yii 2.0 больше не используется метод model() для выполнения запроса. Вместо этого используйте метод find():

// Получение всех *активных* покупателей с сортировкой по их ID:
$customers = Customer::find()
    ->where(['status' => $active])
    ->orderBy('id')
    ->all();
// вернет покупателя с PK равным 1
$customer = Customer::findOne(1);

Метод find() возвращает экземпляр ActiveQuery который является подклассом yii\db\Query. Таким образом, Вы можете использовать все методы запросов класса yii\db\Query.

Вместо возвращения объектов ActiveRecord, Вы можете вызвать метод ActiveQuery::asArray() что бы получить результат в виде массива. Это более эффективно, и особенно полезно, когда нужно вернуть большое количество записей:

$customers = Customer::find()->asArray()->all();

По умолчанию, ActiveRecord теперь сохраняет только измененные атрибуты. В версии 1.1, когда Вы вызывали метод save(), в базу данных сохранялись все атрибуты, независимо от того изменялись они или нет, если не были явно перечислены атрибуты которые нужно сохранить.

Для более подробной информации смотрите раздел ActiveRecord.

Автоматические кавычки в именах таблиц и полей

В Yii 2.0 поддерживается автоматическая расстановка кавычек в именах таблиц и полей баз данных. Имя заключенное в двойные фигурные скобки т.е. {{имя_таблицы}} рассматривается как имя таблицы, а имя заключенное в двойные квадратные скобки т.е. [[имя_поля]] трактуется как имя столбца. К ним будут добавлены кавычки в соответствии с используемым драйвером базы данных:

$command = $connection->createCommand('SELECT [[id]] FROM {{posts}}');
echo $command->sql;  // MySQL: SELECT `id` FROM `posts`

Эта функция особенно полезна, если вы разрабатываете приложение с поддержкой различных СУБД.

User и IdentityInterface

Класс CWebUser из версии 1.1 теперь замещен классом yii\web\User, а класс CUserIdentity теперь упразднен. Вместо этого, Вам нужно использовать yii\web\IdentityInterface, который намного проще в использовании.

Управление URL

Управление URL аналогично версии 1.1. Основным изменением является то, что теперь поддерживаются дополнительные параметры. Например, если Вы определили следующее правило,то оно будет соответствовать post/popular и post/1/popular. В версии 1.1, Вам нужно было использовать два правила для получения такого же результата.

[
    'pattern' => 'post/<page:\d+>/<tag>',
    'route' => 'post/index',
    'defaults' => ['page' => 1],
]

Для более подробной информации смотрите раздел Управление URL.

Расширения

Расширения Yii 1.1 не совместимы с версией 2.0, так что вам придется портировать или переписать их.

Чтобы получить более подробную информацию о расширениях Yii 2.0, смотрите соответствующий раздел документации.

Авторизация