Ivan Asmer 8 anos atrás
pai
commit
9d5e0f721c
1 arquivos alterados com 136 adições e 3 exclusões
  1. 136 3
      YiiDB.md

+ 136 - 3
YiiDB.md

@@ -2,12 +2,145 @@
 
 ## ActiveQuery
 
-Предназначена для получения данных из БД, конструирования запросов. Под капотом преобразует цепочку вызовов (с возвратом `$this`) в SQL, который выполняется *лениво*, т. е. обычно во `view`.
+### ActiveRecord
+
+Для получения объекта **ActiveQuery** по таблице обычно используется статический метод `find` класса **ActiveRecord**:
+
+```php
+//получение объекта ActiveRecord для пользователя
+$query = User::find();
+
+....
+
+//код find
+public static function find()
+{   
+    return new UserQuery(get_called_class());
+}
+```
+
+`UserQuery`, в свою очередь, наследуется от `\yii\db\ActiveQuery`
+
+### Query
+
+`ActiveQuery` унаследован от `Query`, который включает в себя стандартный набор возможностей **SQL** `SELECT`:
+
+```php
+$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`
+
+Параметры могут быть переданы сразу, или добавлены потом:
+
+
+```php
+$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:
+
+```php
+User::find()->where(['username' => "root"])->one(); //Объект ActiveRecord
+```
+
+#### Связи с другими таблицами
+
+Для нормальной работы связанных данных связи должны быть установлены в соответствующих `ActiveRecord` с помощью `hasMany` и `hasOne`:
+
+```php
+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 в каждой записи по нескольким выборкам
+
+```php
+$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` и дополнительные настройки к нему, например *пагинацию*.
 
-## PHPDoc
 
-Формат комментариев, предназначенный для документирования кода. Парсится IDE и генераторами документации.
+```php
+$provider = new ActiveDataProvider([
+    'query' => User::find(),
+    'pagination' => [
+        'pageSize' => 10,
+    ],
+    'sort' => [
+        'defaultOrder' => [
+            'username' => SORT_ASC,
+        ]
+    ],
+]);
+```
+
+$sortedUsers = $provider->getModels();
+
+Обычно *весь* объект `ActiveDataProvider` передается во view, где view может использоваться для настройки сортировок, пагинации и фильтрации.
+