YiiDB.md 6.2 KB

ActiveQuery && ActiveDataProvider

ActiveQuery

ActiveRecord

Для получения объекта ActiveQuery по таблице обычно используется статический метод find класса ActiveRecord:

//получение объекта ActiveRecord для пользователя
$query = User::find();

....

//код find
public static function find()
{   
    return new UserQuery(get_called_class());
}

UserQuery, в свою очередь, наследуется от \yii\db\ActiveQuery

Query

ActiveQuery унаследован от Query, который включает в себя стандартный набор возможностей SQL SELECT:

$query = new Query;
$query->select('id, username')->from('user')

groupBy, having, innerJoin, leftJoin и так далее.

Построение запросов и фильтрация

Yii любит массивы, и в этом случае тоже:

  • Равенство where(['id' => 15]]) // WHERE id = 15
  • AND where(['username' => 'someUser', 'password' => 'password']) // WHERE username = 'someUser' AND password = 'password'
  • OR where(['or',['username' => 'someUser'], ['password' => 'password']) // WHERE username = 'someUser' OR password = 'password'
  • сравнение where(['>', 'registration_date', '2016-12-31') // WHERE registration_date > 2016-12-31
  • подзапрос `where(['in', 'user_id', (new Query())->select('id')->from('enabled_users')] // WHERE user_id in (SELECT id FROM enable_users)

Для уточнения запросов впоследствии, существуют методы andWhere, orWhere, andFilterWhere, orFilterWhere

*FilterWhere отличается от *Where тем. что отбрасывает пустые значения в запросе

JOIN

Для тех или иных присоединений таблиц используются методы join, leftJoin, rightJoin, innerJoin с набором параметров, аналогичным синтаксису SQL:

leftJoin('orders', ['orders.user_id' => 'users.id']) // LEFT JOIN orders ON (orders.user_id = users.id)

$params

Параметры могут быть переданы сразу, или добавлены потом:

$query = new Query;
$query->select('id, username')->from('user')->where(["status" => ":status"])

....

$query->addParams([":status" => "active"])

Query в целом предназначен для конструктирования SELECT запросов и возвращает данные в форме ассоциативных массивов. На этом уровне иерархии объектов доступа данных Yii между запросами и объектами ActiveRecord нет связи.

ActiveQuery

Наследует Query, однако возвращает результат в форме массива соотвествующих ActiveRecord. Набор "оконечных" функций (тех, которые не возвращают $this):

  • one(): одна строка (LIMIT 1)
  • all(): все записи
  • count(): количество записей (count(*))
  • sum(): сумма по указанной колонке
  • average(): средняя по указанной колонке
  • min(): минимум
  • max(): maximum
  • scalar(): возвращает первую ячейку первой строки результата запроса
  • column(): первая колонка
  • exists(): проверка на наличие результата запроса (Empty Set или нет)

ActiveQuery (как и большинство других ORM) работает с помощью chaining, т. е. цепочки вызовов методов. Это работает благодаря тому, что каждый метод, конструирующий запрос в СУБД, возвращает $this:

User::find()->where(['username' => "root"])->one(); //Объект ActiveRecord

Связи с другими таблицами

Для нормальной работы связанных данных связи должны быть установлены в соответствующих ActiveRecord с помощью hasMany и hasOne:

class User extends ActiveRecord {

    public function getOrders(){
        return $this->hasMany(Order::className(), ['users_id' => 'id']])
    }
}

class Order extends ActiveRecord {

    public function getUser(){
        return $this->hasOne(User::className(), ['id' => 'users_id']])
    }
}

Используя with вы можете указать, что нужно загружать данные, включая связи. Под капотом это превращается в LEFT JOIN, который экономит ресурсы, по сравнению с обращением каждый раз к полю orders в каждой записи по нескольким выборкам

$users = User::find()->with('orders')->all() //один запрос
print_r($users[0]->orders) //уже загружено

$slowpokes = User::find()->all(); //один запрос
foreach ($slowpokes as $slowpoke){
    print_r($slowpoke->orders)    //еще стопицот запросов в цикле
}

ActiveDataProvider

Позволяет использовать запрос ActiveQuery и дополнительные настройки к нему, например пагинацию.

$provider = new ActiveDataProvider([
    'query' => User::find(),
    'pagination' => [
        'pageSize' => 10,
    ],
    'sort' => [
        'defaultOrder' => [
            'username' => SORT_ASC,
        ]
    ],
]);

$sortedUsers = $provider->getModels();

Обычно весь объект ActiveDataProvider передается во view, где view может использоваться для настройки сортировок, пагинации и фильтрации.

Expression и функции mySQL

TODO