Введение
На днях, свершилось событие, которое Я и думаю еще немало людей ждали. Авторы Yii Framework выкатили превью-версию.Спустя день здесь на хабре появился обучающий материал, прочтение которого вызвали странные впечатления и после выходных потраченных на изучения кода Yii2, я решил написать свою версию. Надеюсь получится не хуже.
Начало
Вторая версия отличается от первой кардинально. Список в краткой форме:— Отделили ядро от дополнений. Выбросили много классов. Часть из них перекочуют в отдельные, официально поддерживаемые, расширения. Часть просто убрана за ненадобностью.
— Базовый CComponent разделили на Object и Component. Первый осуществляет работу геттеров и сеттеров, второй расширяя первый, добавляя события и поведения.
— Видоизменилось подключение событий и поведений. Подписываемся на событие
$post->on('update', function($event) {
// send email notification
});
Настраиваем компонент
$component = \Yii::createObject(array(
'class' => '\app\components\GoogleMap',
'apiKey' => 'xyz',
// Добавим событие
'on eventName' => array('Event', 'run'),
// Добавим поведение
'as behaviorName' => array(/* Behavior config */),
));
— Добавили новый класс View, теперь у нас настоящий MVC фреймворк. Представление
<?php
use yii\helpers\base\Html;
/**
* Обратите внимание $this в представлении это уже не контроллер.
* Добраться к контроллеру можно $this->context
* @var yii\base\View $this
*/
$this->title = 'Hello world';
?>
<h1><?php echo Html::encode($this->title); ?></h1>
<p class="lead">Привет мир!</p>
* View можно для каждого контроллера устанавливать, или использовать базовый для приложения.— render() контроллера больше ничего не выводит. Оно возвращает данные
public function actionIndex()
{
echo $this->render('index');
}
— В контроллере появились два события, на котрые можно подписываться: beforeAction, afterAction
public function init()
{
$this->on('beforeAction', function($event) {
// отменяем действие
$event->isValid = false;
});
}
— Убраны фильтры контроллера CFilter, теперь все делается через поведения
public function behaviors()
{
return array(
'AccessControl' => array(
'class' => '\yii\web\AccessControl',
'rules' =>array(/* тут ничего не поменялось */),
),
);
}
— В контроллере появился отличный помощник — метод populate
public function actionLogin()
{
$model = new LoginForm();
if ($this->populate($_POST, $model) && $model->login()) {
Yii::$app->response->redirect(array('site/index'));
}
echo $this->render('login', array(
'model' => $model,
));
}
— Добавлены еще несколько статических классов-хелперов: ArrayHelper, StringHelper, SecurityHelper. Все хелперы теперь можно перекрыть через LSB. Ура, воскликнул я, т.к лично мне не раз нужно было перекрыть Html.
— Виджет ActiveForm тоже переписан, и скорее всего заменит форм-билдер CForm. Каждое поле формы теперь может быть представлено как объект ActiveField, который создает ActiveForm
$form = $this->beginWidget('yii\widgets\ActiveForm', array(
'options' => array('class' => 'form-horizontal')
));
echo $form->field($model, 'username')->textInput();
echo $form->field($model, 'password')->passwordInput();
echo $form->field($model, 'rememberMe')->checkbox();
echo Html::tag('div', Html::submitButton('Login', null, null, array('class' => 'btn btn-primary')), array(
'class' => 'form-actions'
));
$this->endWidget();
* Внимание: в Html::tag($tag, $content, $options) — изменили порядок параметров!ActiveRecord
«По большей части, ActiveRecord осталась нетронутой»— написано в предыдущей статье. Верно подмечено — не трогали.
Просто взяли и написали совсем другой ActiveRecord.
— Забываем про model()
— Убран CDbCriteria. Но не пугайтесь, работа с базой стала от этого легче. Появился ActiveQuery, который представляет себя гибрид CActiveFinder и CDbCriteria.
// получаем экземпляр ActiveQuery
$query = Post::find();
// все посты
$posts = $query->all();
// ищем все посты с условием
$posts = $query
->where(array('status' => Post::DRAFT))
->orderBy('time')
->all();
// ищем один пост
$post = $query
->where(array('id' => 10, 'status' => Post::READ))
->one();
// или проще, условие where можно передавать прямо в фабричный метод
$post = Post::find(array('id' => 10, 'status' => Post::READ));
// передав в фабричный метод не массив а число эквивалентно поиску по первичному ключу
$post = Post::find(10)
->where(array('status' => Post::READ))
->one();
// индексируем результат по нужному атрибуту
$posts = $query->indexBy('title')->all();
// результат в виде массива
$posts = $query->asArray()->all();
— Все общие методы теперь статические: getDb, tableName, find*, saveAll*, primaryKey. Выигрыш очевиден.
— Связи, куда же без них. Теперь связи определяются добавлением геттеров
class Post extends ActiveRecord
{
public function getCreator()
{
return $this->hasOne('User', array('id' => 'user_id'));
}
public function getComments()
{
return $this->hasMany('Comment', array('post_id' => 'id'));
}
public function getTrustComments($isTrust = true)
{
return $this->hasMany('Comment', array('post_id' => 'id'))
->where('status = :status', array(
':status' => $isTrust ? self::TRUST : self::UNTRUST,
))
->orderBy('id');
}
}
— Для удобства работы со связями добавили link() и unlink(), который автоматически расставят ключи
$post = Post::find(1);
$comment = new Comment();
$comment->text = 'Yii Framework is cool!';
$post->link('comments', $comment);
— Именованные группы условий есть, но в другом виде. У нас же нет больше CDbCriteria, а значит и массивов условий тоже больше нет. Теперь это методы, причем статические, добавляющие условия в Query
class Post extends \yii\db\ActiveRecord
{
/**
* @param ActiveQuery $query
*/
public static function byCreator($query, $userId)
{
$query->andWhere('user_id = :userId', array('userId' => $userId));
}
/**
* @param ActiveQuery $query
*/
public static function removed($query)
{
$query->andWhere('removed = 1');
}
}
$posts = Post::find()->removed()->all();
$myPosts = Post::find()->byCreator(Yii::$app->user->id)->all();
Все
На этом поставлю точку. Статья получилась большая, много кода, но надеюсь вы выдержали и дочитали.До связи.