mirror of
https://github.com/yiisoft/yii.git
synced 2026-03-04 15:24:07 +01:00
516 lines
36 KiB
Plaintext
516 lines
36 KiB
Plaintext
Реляционная Active Record
|
||
=========================
|
||
|
||
Мы уже рассмотрели использование Active Record (AR) для выбора данных из одной таблицы базы данных.
|
||
В этом разделе мы расскажем, как использовать AR для объединения нескольких связанных таблиц и получить
|
||
объединенный набор данных.
|
||
|
||
Для использования реляционной AR рекомендуется, чтобы все связи отношения
|
||
первичный-внешний ключ были четко определены для объединяемых таблиц.
|
||
Это помогает поддерживать связность и целостность данных.
|
||
|
||
Для наглядности примеров в данном разделе мы будем использовать схему базы данных,
|
||
представленную на этой диаграмме сущность-отношение (ER).
|
||
|
||

|
||
|
||
> Info|Информация: Поддержка ограничений по внешнему ключу различна в разных СУБД.
|
||
> SQLite < 3.6.19 не поддерживает ограничений, но вы, тем не менее, можете их объявить
|
||
> при создании таблиц.
|
||
|
||
Объявление отношения
|
||
----------------------
|
||
|
||
Перед тем, как использовать 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`.
|
||
|
||
Объявляя отношение в AR, мы переопределяем метод [relations()|CActiveRecord::relations] класса [CActiveRecord]. Этот метод возвращает
|
||
массив с конфигурацией отношений. Каждый элемент массива представляет одно отношение в следующем формате:
|
||
|
||
~~~
|
||
[php]
|
||
'VarName'=>array('RelationType', 'ClassName', 'ForeignKey', …дополнительные параметры)
|
||
~~~
|
||
|
||
где `VarName` — имя отношения, `RelationType` указывает на один из четырех типов отношения,
|
||
`ClassName` — имя AR-класса, связанного с данным AR-классом, а
|
||
`ForeignKey` обозначает один или несколько внешних ключей, используемых для связи.
|
||
Кроме того, можно указать ряд дополнительных параметров,
|
||
о которых расскажем чуть позже.
|
||
|
||
В коде ниже показано, как объявить отношение между классами `User` и `Post`.
|
||
|
||
~~~
|
||
[php]
|
||
class Post extends CActiveRecord
|
||
{
|
||
…
|
||
public function relations()
|
||
{
|
||
return array(
|
||
'author'=>array(self::BELONGS_TO, 'User', 'author_id'),
|
||
'categories'=>array(self::MANY_MANY, 'Category',
|
||
'tbl_post_category(post_id, category_id)'),
|
||
);
|
||
}
|
||
}
|
||
|
||
class User extends CActiveRecord
|
||
{
|
||
…
|
||
public function relations()
|
||
{
|
||
return array(
|
||
'posts'=>array(self::HAS_MANY, 'Post', 'author_id'),
|
||
'profile'=>array(self::HAS_ONE, 'Profile', 'owner_id'),
|
||
);
|
||
}
|
||
}
|
||
~~~
|
||
|
||
> Info|Информация: Если внешний ключ составной, мы должны объединить имена полей внешнего ключа и отделить
|
||
друг от друга запятыми. Для типа отношения `MANY_MANY` имя ассоциативной таблицы также должно быть
|
||
указано во внешнем ключе. Например, отношение `categories` в модели `Post` обозначено внешним ключом `tbl_post_category(post_id, category_id)`.
|
||
|
||
При объявлении отношения в AR-классе для каждого отношения в класс неявно добавляется свойство. После выполнения реляционного запроса
|
||
соответствующее свойство будет заполнено связанным(-и) экземпляром(-ами) AR. Например, если `$author` представляет AR-экземпляр `User`, то
|
||
можно использовать `$author->posts` для доступа к связанным экземплярам `Post`.
|
||
|
||
Выполнение реляционного запроса
|
||
---------------------------
|
||
|
||
Самый простой способ выполнить реляционный запрос — считать реляционное свойство AR-класса. Если ранее к этому свойству никто не обращался,
|
||
то будет инициирован реляционный запрос, который соединит связанные таблицы и оставит только данные, соответствующие первичному ключу текущего
|
||
экземпляра AR. Результат запроса будет сохранен в свойстве как экземпляр(-ы) связанного класса.
|
||
Этот подход также известен, как «отложенная загрузка» (lazy loading), т.е.
|
||
реляционный запрос осуществляется только в момент первого обращения к связанным
|
||
объектам. Пример ниже показывает использование этого подхода:
|
||
|
||
~~~
|
||
[php]
|
||
// получаем запись с ID=10
|
||
$post=Post::model()->findByPk(10);
|
||
// Получаем автора записи. Здесь будет выполнен реляционный запрос.
|
||
$author=$post->author;
|
||
~~~
|
||
|
||
> Info|Информация: Если для отношения не существует связанного экземпляра, то соответствующее
|
||
свойство будет null для отношений `BELONGS_TO` и `HAS_ONE` или пустым массивом
|
||
для `HAS_MANY` и `MANY_MANY`.
|
||
Стоит отметить, что отношения `HAS_MANY` и `MANY_MANY` возвращают
|
||
массивы объектов и обращаться к их свойствам необходимо в цикле, иначе
|
||
можно получить ошибку «Trying to get property of non-object».
|
||
|
||
Способ отложенной загрузки удобен, но не всегда эффективен. Например, если мы захотим
|
||
получить информацию об авторе `N` записей, использование отложенной загрузки
|
||
потребует выполнения `N` запросов для объединения. В данной ситуации,
|
||
нам поможет метод «жадной загрузки» (eager loading).
|
||
|
||
Этот подход заключается в загрузке всех связанных экземпляров AR одновременно с
|
||
основным экземпляром AR. Реализуется этот подход путем использования в AR метода
|
||
[with()|CActiveRecord::with] в связке с методом [find|CActiveRecord::find] или
|
||
[findAll|CActiveRecord::findAll].
|
||
Например:
|
||
~~~
|
||
[php]
|
||
$posts=Post::model()->with('author')->findAll();
|
||
~~~
|
||
|
||
Код выше вернет массив экземпляров `Post`. В отличие от отложенной загрузки, свойство `author` в каждой записи
|
||
заполнено связанным экземпляром `User` еще до обращения к свойству. Вместо выполнения объединяющего запроса
|
||
для каждой записи, жадная загрузка получает все записи вместе с авторами в одном объединяющем запросе!
|
||
|
||
В методе [with()|CActiveRecord::with] можно указать множество имен отношений и жадная загрузка вернет их за один раз.
|
||
Например, следующий код вернет записи вместе с их авторами и категориями:
|
||
|
||
~~~
|
||
[php]
|
||
$posts=Post::model()->with('author','categories')->findAll();
|
||
~~~
|
||
|
||
Кроме того, можно осуществлять вложенную жадную загрузку. Для этого вместо простого списка имен отношений, мы передаем методу
|
||
[with()|CActiveRecord::with] имена отношений, упорядоченных иерархически, как в примере ниже:
|
||
|
||
~~~
|
||
[php]
|
||
$posts=Post::model()->with(
|
||
'author.profile',
|
||
'author.posts',
|
||
'categories')->findAll();
|
||
~~~
|
||
|
||
Пример выше вернет нам все записи с их авторами и категориями, а также профиль каждого автора и все его записи.
|
||
|
||
Начиная с версии 1.1.0, жадная загрузка может быть выполнена путём указания
|
||
свойства [CDbCriteria::with]:
|
||
|
||
~~~
|
||
[php]
|
||
$criteria=new CDbCriteria;
|
||
$criteria->with=array(
|
||
'author.profile',
|
||
'author.posts',
|
||
'categories',
|
||
);
|
||
$posts=Post::model()->findAll($criteria);
|
||
~~~
|
||
|
||
или
|
||
|
||
~~~
|
||
[php]
|
||
$posts=Post::model()->findAll(array(
|
||
'with'=>array(
|
||
'author.profile',
|
||
'author.posts',
|
||
'categories',
|
||
)
|
||
);
|
||
~~~
|
||
|
||
Параметры реляционного запроса
|
||
------------------------------
|
||
|
||
Выше мы упоминали о том, что в реляционном запросе можно указать дополнительные параметры.
|
||
Эти параметры — пары имя-значение — используются для тонкой настройки реляционного запроса.
|
||
Список параметров представлен ниже.
|
||
|
||
- `select`: список выбираемых полей для связанного AR-класса. По умолчанию значение параметра равно '*',
|
||
т.е. выбираются все поля таблицы. Для используемых столбцов должны быть разрешены конфликты имён.
|
||
|
||
- `condition`: соответствует оператору `WHERE`, по умолчанию значение параметра пустое.
|
||
Для используемых столбцов должны быть разрешены конфликты имён.
|
||
|
||
- `params`: параметры для связывания в генерируемом SQL-выражении. Параметры передаются как массив пар имя-значение. Параметр
|
||
доступен, начиная с версии 1.0.3;
|
||
|
||
- `on`: соответствует оператору `ON`. Условие, указываемое в этом параметре,
|
||
будет добавлено к условию объединения с использованием оператора `AND`. Для используемых столбцов должны быть разрешены конфликты имён.
|
||
Данный параметр неприменим для отношений типа `MANY_MANY`. Параметр доступен, начиная с версии 1.0.2;
|
||
|
||
- `order`: соответствует оператору `ORDER BY`, по умолчанию значение параметра пустое.
|
||
Для используемых столбцов должны быть разрешены конфликты имён.
|
||
|
||
- `with`: список дочерних связанных объектов, которые должны быть загружены с самим объектом.
|
||
Неправильное использование данной возможности может привести к бесконечному циклу.
|
||
|
||
- `joinType`: тип объединения для отношения. По умолчанию значение параметра равно `LEFT
|
||
OUTER JOIN`;
|
||
|
||
- `alias`: псевдоним таблицы, ассоциированной с отношением. Этот параметр доступен с версии 1.0.1. По умолчанию значение параметра
|
||
равняется null, что означает, что псевдоним соответствует имени отношения.
|
||
|
||
- `together`: параметр, устанавливающий необходимость принудительного объединения таблицы, ассоциированной с этим отношением,
|
||
с другими таблицами. Этот параметр имеет смысл только для отношений типов `HAS_MANY` и `MANY_MANY`. Если параметр не установлен или
|
||
равен false, тогда каждое отношение `HAS_MANY` или `MANY_MANY` будет использовать отдельный SQL запрос для связанных данных,
|
||
что может улучшить скорость выполнения запроса т.к. уменьшается количество выбираемых данных.
|
||
Если данный параметр равен `true`, зависимая таблица при запросе будет всегда
|
||
объединяться с основной, то есть будет сделан один запрос даже в том случае, если
|
||
к основной таблице применяется постраничная разбивка. Если данный параметр не
|
||
задан, зависимая таблица будет объединена с основной только в случае, когда не
|
||
к основной таблице не применяется постраничная разбивка. Более подробное описание
|
||
можно найти в разделе «производительность реляционного запроса».
|
||
Параметр доступен, начиная с версии 1.0.3;
|
||
|
||
- `join`: дополнительный оператор `JOIN`. По умолчанию пуст. Этот параметр
|
||
доступен с версии 1.1.3.
|
||
|
||
- `group`: соответствует оператору `GROUP BY`, по умолчанию значение параметра пустое.
|
||
Для используемых столбцов должны быть разрешены конфликты имён.
|
||
|
||
- `having`: соответствует оператору `HAVING`, по умолчанию значение параметра пустое.
|
||
Для используемых столбцов должны быть разрешены конфликты имён. Параметр доступен, начиная с версии 1.0.1.
|
||
|
||
- `index`: имя столбца, значения которого должны быть использованы в
|
||
качестве ключей массива, хранящего связанные объекты. Без установки этого
|
||
параметра, массив связанных объектов использует целочисленный индекс,
|
||
начинающийся с нуля. Параметр может быть установлен только для отношений
|
||
`HAS_MANY` и `MANY_MANY`. Параметр доступен с версии 1.0.7.
|
||
|
||
Кроме того, для отложенной загрузки некоторых типов отношений доступен ряд дополнительных параметров:
|
||
|
||
- `limit`: параметр для ограничения количества строк в выборке. Параметр не применим для отношений `BELONGS_TO`;
|
||
|
||
- `offset`: параметр для указания начальной строки выборки. Параметр не применим для отношений `BELONGS_TO`.
|
||
|
||
Ниже мы изменим определение отношения `posts` в модели `User`, добавив несколько вышеприведенных параметров:
|
||
|
||
~~~
|
||
[php]
|
||
class User extends CActiveRecord
|
||
{
|
||
public function relations()
|
||
{
|
||
return array(
|
||
'posts'=>array(self::HAS_MANY, 'Post', 'author_id',
|
||
'order'=>'posts.create_time DESC',
|
||
'with'=>'categories'),
|
||
'profile'=>array(self::HAS_ONE, 'Profile', 'owner_id'),
|
||
);
|
||
}
|
||
}
|
||
~~~
|
||
|
||
Теперь при обращении к `$author->posts`, мы получим записи автора, отсортированные
|
||
в обратном порядке по времени их создания. Для каждой записи будут загружены
|
||
её категории.
|
||
|
||
Устранение конфликта имён столбцов
|
||
----------------------------------
|
||
|
||
При совпадении имён столбцов в двух и более соединяемых таблицах,
|
||
приходится решать конфликт имён. Это делается при помощи добавления
|
||
псевдонима таблицы к имени столбца.
|
||
|
||
В реляционном запросе псевдоним главной таблицы всегда равен `t`,.
|
||
Имя псевдонима относящейся к ней таблице по умолчанию соответствует имени отношения.
|
||
К примеру, в коде ниже псевдонимы для `Post` и `Comment` соответственно
|
||
`t` и `comments`:
|
||
|
||
~~~
|
||
[php]
|
||
$posts=Post::model()->with('comments')->findAll();
|
||
~~~
|
||
|
||
Допустим, что и в `Post` и в `Comment` есть столбец `create_time`, в котором
|
||
хранится время создания записи или комментария, и нам необходимо получить записи
|
||
вместе с комментариями к ним, отсортированные сначала по времени создания
|
||
записи, а затем по времени написания комментария. Для этого нам понадобится
|
||
устранить конфликт столбцов `create_time` следующим образом:
|
||
|
||
~~~
|
||
[php]
|
||
$posts=Post::model()->with('comments')->findAll(array(
|
||
'order'=>'t.create_time, comments.create_time'
|
||
));
|
||
~~~
|
||
|
||
> Note|Примечание: разрешение конфликта имён изменилось по сравнению с версией 1.1.0.
|
||
> До этого по умолчанию Yii генерировал псевдоним таблицы для каждой связанной таблицы,
|
||
> а для его использования необходимо было использовать префикс `??.` в нужных местах запроса.
|
||
> Также в версиях 1.0.x псевдоним главной таблицы соответствовал имени таблицы.
|
||
|
||
Динамические параметры реляционного запроса
|
||
-------------------------------------------
|
||
|
||
Начиная с версии 1.0.2, мы можем использовать динамические параметры как для параметра
|
||
[with()|CActiveRecord::with], так и для параметра `with`. Динамические параметры переопределяют существующие
|
||
параметры в соответствии с описанием метода [relations()|CActiveRecord::relations]. К примеру, если для модели `User`, приведенной выше,
|
||
мы хотим воспользоваться жадной загрузкой для получения записей автора в порядке возрастания (параметр `order` в определении отношения
|
||
задает убывающий порядок), можно сделать это следующим образом:
|
||
|
||
~~~
|
||
[php]
|
||
User::model()->with(array(
|
||
'posts'=>array('order'=>'posts.create_time ASC'),
|
||
'profile',
|
||
))->findAll();
|
||
~~~
|
||
|
||
Начиная с версии 1.0.5 динамические параметры в реляционных запросах можно использовать вместе с
|
||
отложенной загрузкой. Для этого необходимо вызвать метод с тем же именем, что и
|
||
имя связи, и передать параметры как его аргумент. К примеру, следующий код
|
||
вернёт публикации пользователя, у которых `status` равен 1:
|
||
|
||
~~~
|
||
[php]
|
||
$user=User::model()->findByPk(1);
|
||
$posts=$user->posts(array('condition'=>'status=1'));
|
||
~~~
|
||
|
||
Производительность реляционного запроса
|
||
---------------------------------------
|
||
|
||
Как было описано выше, жадная загрузка используется, главным образом, когда
|
||
требуется получить множество связанных объектов. В этом случае соединением
|
||
всех таблиц генерируется большой сложный SQL-запрос. Такой запрос во многих случаях
|
||
является предпочтительным т.к. упрощает фильтрацию по значению столбца связанной таблицы.
|
||
Тем не менее, в некоторых случаях такие запросы не являются эффективными.
|
||
|
||
Рассмотрим пример, в котором нам надо найти последние записи вместе с их комментариями.
|
||
Учитывая, что у каждой записи 10 комментариев, при использовании одного большого SQL-запроса
|
||
мы получим множество лишних данных так как каждая запись будет повторно выбираться с каждым
|
||
её комментарием. Теперь попробуем по-другому: сначала выберем последние записи, а затем комментарии к ним.
|
||
В данном случае нам необходимо выполнить два SQL запроса. Плюс в том, что в полученных данных не будет
|
||
ничего лишнего.
|
||
|
||
Так какой подход более эффективен? Абсолютно верного ответа на этот вопрос нет. Выполнение одного большого SQL запроса
|
||
может быть более эффективным так как СУБД не приходится лишний раз разбирать и выполнять дополнительные запросы.
|
||
С другой стороны, используя один SQL запрос, мы получаем больше лишних данных и соответственно нам требуется больше
|
||
времени на их передачу и обработку.
|
||
|
||
По этой причине в Yii имеется параметр запроса `together`, позволяющий выбрать между двумя описанным подходами.
|
||
По умолчанию Yii использует первый подход, то есть генерирует один SQL запрос для жадной загрузки.
|
||
Если выставить параметр `together` в false, некоторые таблицы будут объединены отдельными SQL запросами.
|
||
К примеру, для того, чтобы использовать второй подход для выборки последних записей с комментариями к ним,
|
||
мы можем описать отношение `comments` в классе `Post` следующим образом:
|
||
|
||
~~~
|
||
[php]
|
||
public function relations()
|
||
{
|
||
return array(
|
||
'comments' => array(self::HAS_MANY, 'Comment', 'post_id', 'together'=>false),
|
||
);
|
||
}
|
||
~~~
|
||
|
||
Для жадной загрузки мы можем задать эту опцию динамически:
|
||
|
||
~~~
|
||
[php]
|
||
$posts = Post::model()->with(array('comments'=>array('together'=>false)))->findAll();
|
||
~~~
|
||
|
||
> Note|Примечание: В версии 1.0.x по умолчанию генерировалось и выполнялось
|
||
> `N+1` SQL запросов при наличии `N` связей типа `HAS_MANY` или `MANY_MANY`.
|
||
> Каждая связь `HAS_MANY` или `MANY_MANY` выполнялась в своём запросе. Вызовом
|
||
> метода `together()` после `with()` можно было сгенерировать и выполнить единый
|
||
> SQL запрос:
|
||
>
|
||
> ~~~
|
||
> [php]
|
||
> $posts=Post::model()->with(
|
||
> 'author.profile',
|
||
> 'author.posts',
|
||
> 'categories')->together()->findAll();
|
||
> ~~~
|
||
>
|
||
|
||
Статистический запрос
|
||
-----------------
|
||
|
||
> Note|Примечание: статистические запросы доступны, начиная с версии 1.0.4.
|
||
|
||
Помимо реляционных запросов, описанных выше, Yii также поддерживает так называемые статистические запросы (или запросы агрегирования).
|
||
Этот тип запросов используется для получения агрегированных данных, относящихся к связанным объектам, например количество комментариев
|
||
к каждой записи, средний рейтинг для каждого наименования продукции и т.д.
|
||
Статистические запросы могут быть использованы только для объектов, связанных отношениями `HAS_MANY` (например, у записи есть много
|
||
комментариев) или `MANY_MANY` (например, запись принадлежит многим категориям, а к категории относится множество записей).
|
||
|
||
Выполнение статистического запроса аналогично выполнению реляционного запроса в соответствии с описанием выше. Первым делом необходимо
|
||
объявить статистический запрос в методе [relations()|CActiveRecord::relations] класса [CActiveRecord].
|
||
|
||
~~~
|
||
[php]
|
||
class Post extends CActiveRecord
|
||
{
|
||
public function relations()
|
||
{
|
||
return array(
|
||
'commentCount'=>array(self::STAT, 'Comment', 'post_id'),
|
||
'categoryCount'=>array(self::STAT, 'Category', 'post_category(post_id, category_id)'),
|
||
);
|
||
}
|
||
}
|
||
~~~
|
||
|
||
Выше мы объявили два статистических запроса: `commentCount` подсчитывает количество комментариев к записи, а `categoryCount`
|
||
считает количество категорий, к которым относится запись. Обратите внимание, что отношение между `Post` и `Comment` — типа `HAS_MANY`, а
|
||
отношение между `Post` и `Category` — типа `MANY_MANY` (с использованием преобразующей таблицы `post_category`). Как можно видеть,
|
||
порядок объявления очень схож с объявлением отношений, описанных выше. Единственное различие состоит в том, что в данном случае тип отношения
|
||
равен `STAT`.
|
||
|
||
За счет объявленных отношений мы можем получить количество комментариев для записи, используя выражение `$post->commentCount`.
|
||
В момент первого обращения к данному свойству для получения соответствующего результата неявным образом выполняется SQL-выражение.
|
||
Как мы уже говорили, это называется подходом *отложенной загрузки*. Можно также использовать *жадный* вариант загрузки, если необходимо
|
||
получить количество комментариев к нескольким записям:
|
||
|
||
~~~
|
||
[php]
|
||
$posts=Post::model()->with('commentCount', 'categoryCount')->findAll();
|
||
~~~
|
||
|
||
Выражение выше выполняет три SQL-запроса для получения всех записей вместе с значениями количества комментариев к ним и количества категорий.
|
||
В случае отложенной загрузки нам бы понадобилось выполнить `2*N+1` SQL-запросов для `N` записей.
|
||
|
||
По умолчанию статистический запрос считает количество с использованием выражения `COUNT`.
|
||
Его можно уточнить путем указания дополнительных параметров в момент объявления в методе [relations()|CActiveRecord::relations].
|
||
Доступные параметры перечислены ниже:
|
||
|
||
- `select`: статистическое выражение, по умолчанию равно `COUNT(*)`, что соответствует количеству дочерних объектов;
|
||
|
||
- `defaultValue`: значение, которое присваивается в случае, если результат статистического запроса для записи отрицателен.
|
||
Например, если запись не имеет ни одного комментария, то свойству `commentCount` будет присвоено это значение. По умолчанию значение
|
||
данного параметра равно 0;
|
||
|
||
- `condition`: соответствует оператору `WHERE`, по умолчанию значение параметра пустое;
|
||
|
||
- `params`: параметры для связывания в генерируемом SQL-выражении. Параметры передаются
|
||
как массив пар имя-значение;
|
||
|
||
- `order`: соответствует оператору `ORDER BY`, по умолчанию значение параметра пустое;
|
||
|
||
- `group`: соответствует оператору `GROUP BY`, по умолчанию значение параметра пустое;
|
||
|
||
- `having`: соответствует оператору `HAVING`, по умолчанию значение параметра пустое.
|
||
|
||
Реляционные запросы с именованными группами условий
|
||
---------------------------------------------------
|
||
|
||
> Note|Примечание: Группы условий поддерживаются, начиная с версии 1.0.5.
|
||
|
||
В реляционном запросе [именованные группы условий](/doc/guide/database.ar#named-scopes)
|
||
могут быть использованы двумя способами. Их можно применить к основной модели и
|
||
к связанным моделям.
|
||
|
||
Следущий код показывает случай с основной моделью:
|
||
|
||
~~~
|
||
[php]
|
||
$posts=Post::model()->published()->recently()->with('comments')->findAll();
|
||
~~~
|
||
|
||
Данный код очень похож на нереляционные запросы. Единственное отличие в том, что
|
||
у нас присутствует вызов `with()` после вызовов групп условий. Данный запрос
|
||
вернёт недавно опубликованные записи вместе с комментариями к ним.
|
||
|
||
В следующем примере показано, как применить группы условий к связанным моделям:
|
||
|
||
~~~
|
||
[php]
|
||
$posts=Post::model()->with('comments:recently:approved')->findAll();
|
||
~~~
|
||
|
||
Этот запрос вернёт все записи вместе с одобренными комментариями. Здесь `comments`
|
||
относится к имени отношения. `recently` и `approved` — именованные группы, описанные
|
||
в модели `Comment`. Имя отношения и группы параметров разделяются двоеточием.
|
||
|
||
Именованные группы могут быть использованы при описании отношений модели в
|
||
методе [CActiveRecord::relations()] в параметре `with`. В следующем примере
|
||
при обращении к `$user->posts` вместе с публикациями будут получены все
|
||
*одобренные* комментарии.
|
||
|
||
~~~
|
||
[php]
|
||
class User extends CActiveRecord
|
||
{
|
||
public function relations()
|
||
{
|
||
return array(
|
||
'posts'=>array(self::HAS_MANY, 'Post', 'author_id',
|
||
'with'=>'comments:approved'),
|
||
);
|
||
}
|
||
}
|
||
~~~
|
||
|
||
> Note|Примечание: Именованные группы параметров, применяемые к реляционным моделям,
|
||
должны описываться в методе [CActiveRecord::scopes], поэтому они не могут быть
|
||
параметризованы.
|
||
|
||
<div class="revision">$Id: database.arr.txt 2782 2010-12-28 16:18:06Z qiang.xue $</div> |