Yii реляційні запити

Реляційна Active Record

Ми вже розглянули використання Active Record (AR) для вибору даних з однієї таблиці бази даних. У цьому розділі ми розповімо, як використовувати AR для з'єднання декількох пов'язаних таблиць і отримання набору пов'язаних даних. Перед використанням реляційної AR рекомендується встановити обмеження зовнішніх ключів для таблиць бази даних. Це дозволить забезпечити несуперечливість та цілісність даних, що зберігаються. Для наочності прикладів у цьому розділі ми будемо використовувати схему бази даних, представлену на наступній діаграмі сутність-зв'язок (ER).

Інформація: Підтримка обмежень зовнішніх ключів різниться в різних СУБД. SQLite 3.6.19 і більш ранні версії не підтримує обмежень, але ви, тим не менш, можете їх оголосити при створенні таблиць. Движок MySQL MyISAM не підтримує зовнішні ключі.

1. Установка зв'язків між AR-класами

Перед тим як використовувати AR для виконання реляційних запитів, нам необхідно налагодити зв'язки між AR-класами. Зв'язок між двома AR-класами безпосередньо залежить від зв'язків між відповідними таблицями бази даних. З точки зору БД, зв'язок між таблицями A і В може бути трьох типів: один-ко-многим (наприклад, tbl_user і tbl_post), один-до-одного (наприклад, tbl_user і tbl_profile) і багато-до-багатьох (наприклад, tbl_category і tbl_post). У AR існує чотири типи зв'язків:
  • BELONGS_TO. якщо зв'язок між А і В один-ко-многим, значить В належить А (наприклад, Post належить User);
  • HAS_MANY. якщо зв'язок між таблицями А і В один-ко-многим, значить у А є багато В (наприклад, у User є багато Post);
  • HAS_ONE. це окремий випадок HAS_MANY. де А може мати максимум одне В (наприклад, у User є тільки один Profile);
  • MANY_MANY. цей зв'язок відповідає типу зв'язку багато-до-багатьох в БД. Оскільки багато СУБД не підтримують безпосередньо цей тип зв'язку, потрібно асоціативна таблиця для перетворення зв'язку багато-до-багатьох в зв'язку один-ко-многим. У нашій схемі бази даних цієї мети служить таблиця tbl_post_category. У термінології AR зв'язок MANY_MANY можна описати як комбінацію BELONGS_TO і HAS_MANY. Наприклад, Post належить багатьом Category. а у Category є багато Post.
Існує п'ятий, спеціальний тип зв'язку, який призначений для статистичних запитів над пов'язаними записами (запити агрегування) - називається він STAT. Більш детально з ним можна ознайомитися в розділі Статистичний запит. Установка зв'язків проводиться всередині методу relations () класу CActiveRecord. Цей метод повертає масив з конфігурацією зв'язків. Кожен елемент масиву представляє одну зв'язок в наступному форматі:

де VarName - ім'я зв'язку, RelationType вказує на один з чотирьох типів зв'язків, ClassName - ім'я AR-класу, пов'язаного з даним класом, а ForeignKey позначає один або кілька зовнішніх ключів, які використовуються для зв'язку. Крім того, можна вказати ряд додаткових параметрів, про які буде розказано пізніше. У наведеному нижче коді показано, як встановити зв'язок між класами User і Post.

2. Виконання реляційного запиту

Найпростіший спосіб виконати реляційний запит - використовувати реляционное властивість AR-класу. Якщо звернення до цієї властивості проводиться вперше, то буде виконаний реляційний запит, який з'єднає зв'язані таблиці і залишить тільки дані, відповідні первинному ключу поточного екземпляра AR. Результат запиту буде збережено у властивості як екземпляр (або масив екземплярів) пов'язаного класу. Цей підхід також відомий як «відкладена завантаження» (lazy loading), при якій безпосередній запит виконується тільки в момент першого звернення до зв'язаних об'єктів. Нижче наведено приклад використання цього підходу:

Крім того, можна здійснювати вкладену жадібну завантаження. Для цього замість простого списку імен зв'язків, ми передаємо методу with () імена зв'язків, упорядкованих ієрархічно, як у наступному прикладі:

3. Реляційний запит без отримання зв'язаних моделей

4. Параметри реляційного запиту

5. Усунення конфлікту імен стовпців

Підказка: Ім'я таблиці зв'язку за замовчуванням дорівнює назвою самої зв'язку. Майте на увазі, що при використанні однієї зв'язку всередині іншої буде використано назву останньої з них. При цьому назва батьківської зв'язки не буде використано в якості префікса. Наприклад, псевдонімом зв'язку 'author.group' є 'group', а не 'author.group'.

Ви можете уникнути конфлікту псевдонімів таблиць задавши властивість зв'язку alias.

6. Динамічні параметри реляційного запиту

7. Продуктивність реляційного запиту

Для жадібної завантаження ми можемо задати цей параметр динамічно:

8. Статистичний запит

9. Реляційні запити з іменованими групами умов

У реляционном запиті іменовані групи умов можуть бути використані двома способами. Їх можна застосувати до основної моделі і до пов'язаних моделям. Наступний код ілюструє випадок їх застосування до основної моделі:

У версії 1.1.7 з'явилася можливість передавати параметри іменованих груп умов зв'язку. Наприклад, якщо в Post є іменована група умов rated. приймаюча мінімальний рейтинг запису, використовувати її в User можна наступним чином: Примітка: до версії 1.1.7 іменовані групи умов, що застосовуються до реляційних моделей, повинні бути описані в CActiveRecord :: scopes. Тому вони не можуть бути параметризовані.

10. Реляційні запити з through

При використанні through визначення зв'язку має виглядати наступним чином:

HAS_MANY through

HAS_MANY through ER

Yii реляційні запити

HAS_ONE through

HAS_ONE through ER

through з собою

through можна використовувати для моделі, пов'язаної з собою через міст. У нашому випадку це користувач, який навчає інших користувачів:

through self ER

Зв'язки для даного випадку визначаються наступним чином:

Схожі статті