В батле Query VS ActiveRecord - нет победителя - это инструменты для решения разных задач.
Но я хочу отвлечься от вашего вопроса и поинтересоваться настроены ли в вашей БД внешние ключи ? Если нет, то советую начать изучение именно с этого момента, понимание внешних ключей в MySQL.
После чего, нужно очень вдумчиво и хорошо прочесть официальную документацию на тему ActiveRecord (
www.yiiframework.com/doc-2.0/guide-db-active-recor...
После этого, у вас должна сложиться более целостная картинка о том, как это использовать вместе и что за что отвечает.
Теперь вернемся к использованию Query и AR, ну тут все просто, приведу просто пример кода
/**
* Class VehicleQuery
* @package frontend\modules\v1\models\vehicle
*/
class VehicleQuery extends ActiveQuery
{
public $type;
/**
* @param \yii\db\QueryBuilder $builder
* @return \yii\db\Query
*/
public function prepare($builder)
{
if ($this->type !== null) {
$this->andWhere([Vehicle::tableName() . '.vehicle_type' => $this->type]);
}
return parent::prepare($builder);
}
/**
* Returns popular and active vehicles based on vehicle type
* @return $this
*/
public function popular()
{
$this->andWhere([
Vehicle::tableName() . '.promoted' => 1,
Vehicle::tableName() . '.deleted' => 0,
Vehicle::tableName() . '.status' => '1',
Vehicle::tableName() . '.in_use' => 1
]);
return $this;
}
/**
* @return $this
*/
public function active()
{
$this->andWhere([
Vehicle::tableName() . '.status' => '1',
Vehicle::tableName() . '.deleted' => 0
]);
return $this;
}
/**
* @return $this
*/
public function inUse()
{
$this->andWhere([Vehicle::tableName() . '.in_use' => 1]);
return $this;
}
/**
* Returns most rated vehicles
* @return $this
*/
public function rated()
{
$this->addOrderBy([
Vehicle::tableName() . '.rating' => SORT_DESC,
Vehicle::tableName() . '.created_at' => SORT_DESC
]);
return $this;
}
/**
* Returns most recently vehicles
* @return $this
*/
public function recently()
{
$this->addOrderBy([
Vehicle::tableName() . '.created_at' => SORT_DESC,
Vehicle::tableName() . '.rating' => SORT_DESC
]);
return $this;
}
}
Мы имеем модель Vehicle и для работы с этой моделью нам необходимо строить запросы, именно этим и занимается класс VehicleQuery - он берет на себя эту ответственность. Очень важно что бы Query класс был ответственный только за построение запросов, методы не должны возвращать find или save, они должны возвращать только экземпляр Query.
Приведу код модели Vehicle
class Vehicle extends ActiveRecord
{
public static function find()
{
return new VehicleQuery(get_called_class());
}
/**
* @return \yii\db\ActiveQuery
*/
public function getCarBrand()
{
return $this->hasOne(CarBrand::className(), ['id' => 'car_brand_id']);
}
/**
* @return \yii\db\ActiveQuery
*/
public function getCarGeneration()
{
return $this->hasOne(CarGeneration::className(), ['id' => 'car_generation_id']);
}
/**
* @return \yii\db\ActiveQuery
*/
public function getLanguage()
{
return $this->hasOne(Language::className(), ['id' => 'language_id']);
}
/**
* @return \yii\db\ActiveQuery
*/
public function getUser()
{
return $this->hasOne(User::className(), ['id' => 'user_id']);
}
/**
* @return \yii\db\ActiveQuery
*/
public function getPosts()
{
return $this->hasMany(Post::className(), ['car_id' => 'id']);
}
}
Модель описывает entity, rules, relations, attributes - собственно это главная ответственность модели, никакую дополнительную логику в моделе не рекомендуется имплементировать.
Из выше описанного ваш запрос может выглядеть следующим образом
Vehicle::find()->with(['user', 'posts'])->active()->recently();
Этот запрос выберет активные транспортные средства за последнее время со связями getUser(владелец) и getPosts(блоги).