Реляційна 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.
де 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
HAS_ONE through
HAS_ONE through ER
through з собою
through можна використовувати для моделі, пов'язаної з собою через міст. У нашому випадку це користувач, який навчає інших користувачів:
through self ER
Зв'язки для даного випадку визначаються наступним чином: