Active Record
В Yii 2.0 внесено множество изменений в работу Active Record. Два основных из них включают в себя построение запросов и работу со связями.
Класс CDbCriteria
версии 1.1 был заменен [[yii\db\ActiveQuery]]. Этот класс наследуется от [[yii\db\Query]] и таким образом получает все методы, необходимые для построения запроса. Чтобы начать строить запрос следует вызвать метод [[yii\db\ActiveRecord::find()]]:
// Получаем всех *активных* клиентов и сортируем их по ID
$customers = Customer::find()
->where(['status' => $active])
->orderBy('id')
->all();
Для объявления связи следует просто объявить геттер, который возвращает объект [[yii\db\ActiveQuery|ActiveQuery]]. Имя свойства, определённое геттером, представляет собой название связи. Например, следующий код объявляет связь orders
(в версии 1.1, вам нужно было бы объявить связи в одном месте — методе relations()
):
class Customer extends \yii\db\ActiveRecord
{
public function getOrders()
{
return $this->hasMany('Order', ['customer_id' => 'id']);
}
}
Теперь вы можете использовать выражение $customer->orders
для получения всех заказов клиента из связанной таблицы. Вы также можете использовать следующий код, чтобы применить нужные условия «на лету»:
$orders = $customer->getOrders()->andWhere('status=1')->all();
Yii 2.0 осуществляет жадную загрузку связи не так, как это было в 1.1. В частности, в версии 1.1 для выбора данных из основной и связанной таблиц будет использован запрос JOIN. В Yii 2.0 будут выполнены два запроса без использования JOIN: первый запрос возвращает данные для основной таблицы, а второй, осуществляющий фильтрацию по первичным ключами основной таблицы — для связанной.
Вместо того, чтобы при выборке большого количества записей возвращать объекты [[yii\db\ActiveRecord|ActiveRecord]], вы можете использовать в построении запроса метод [[yii\db\ActiveQuery::asArray()|asArray()]]. Это заставит вернуть результат запроса в виде массива, что при большом количестве записей может существенно снизить затрачиваемое процессорное время и объём потребляемой памяти. Например:
$customers = Customer::find()->asArray()->all();
Ещё одно изменение связано с тем, что вы больше не можете определять значения по умолчанию через public свойства. Вы должны установить их в методе init
вашего класса, если это требуется.
public function init()
{
parent::init();
$this->status = self::STATUS_NEW;
}
Также в версии 1.1 были некоторые проблемы с переопределением конструктора ActiveRecord. Данные проблемы отсутствуют в версии 2.0. Обратите внимание, что при добавлении параметров в конструктор, вам, возможно, понадобится переопределить метод [[yii\db\ActiveRecord::instantiate()]].
Существует также множество других улучшений в ActiveRecord. Подробнее о них можно узнать в разделе «Active Record».