CakePHP Containable Behavior
CakePHP Июль 31st, 2008
Новым аддоном в ядре CakePHP является Containable Behavior (далее буду писать CB, для удобства). Это поведение модели используется для ограничений в выборках связанных моделей при вызове find-методов.
Другими словами: при использовании CB вы можете указать какие модели вам необходимы в массиве, который вернет find-метод. Кроме того, можно указать и список полей, который вас интересует в связанной модели. Этот класс также решает задачу поиска по данным связанных моделей.
Слишком обезображенный текст получается выше, поэтому лучше всего разбираться со всем вышесказанным на примерах.
Оригинал статьи от разработчиков CakePHP: Containable Behavior
Для использования CB необходимо выполнить стандартную процедуру: заполнить поле $actsAs в вашей модели:
class Post extends AppModel {var $actsAs = array('Containable');}
Для подключения на лету используем метод attach():
$this->Post->Behaviors->attach('Containable');
Итак, имеем пример модели Post, которая имеет много комментов (hasMany Comment),
а также имеет много тегов и в тоже время пренадлежит многим тегам (hasAndBelongsToMany Tag).
Стандартный вызов find() вернет примерно следующий результат:
debug($this->Post->find('all'));[0] => Array([Post] => Array([id] => 1[title] => First article[content] => aaa[created] => 2008-05-18 00:00:00)[Comment] => Array([0] => Array([id] => 1[post_id] => 1[author] => Daniel[email] => dan@example.com[website] => http://example.com[comment] => First comment[created] => 2008-05-18 00:00:00)[1] => Array([id] => 2[post_id] => 1[author] => Sam[email] => sam@example.net[website] => http://example.net[comment] => Second comment[created] => 2008-05-18 00:00:00))[Tag] => Array([0] => Array([id] => 1[name] => A)[1] => Array([id] => 2[name] => B)))[1] => Array([Post] => Array(...
Согласитесь, в большинстве случаев, вам не нужно столько данных в результате. Нужна помощь CB.
Чтобы получить только информацию о посте, используем следующую конструкцию:
$this->Post->contain();$this->Post->find('all');
Также можно настроить выборку во втором параметре метода find():
$this->Post->find('all', array('contain' => false));
Итого, имеем только наши модельки. Ничего личнего больше нет:
[0] => Array([Post] => Array([id] => 1[title] => First article[content] => aaa[created] => 2008-05-18 00:00:00))[1] => Array([Post] => Array([id] => 2[title] => Second article[content] => bbb[created] => 2008-05-19 00:00:00))
Цитата:
This sort of help isn’t new: in fact, you can do that without the ContainableBehavior doing something like this:
$this->Post->recursive = -1;$this->Post->find('all');
В переводе означает, что ничего нового до этой строки мы не нашли. Трудно не согласиться :)
Поле recursive говорит о том, до какого уровня вложенности выбирать связанные модели.
Значение -1 скажет модели, что нужна только она.
А вот теперь примеры по делу. Нужно выбрать посты только с тегами,
без комментариев. Recursive здесь никак не поможет.
Делаем энифинк лайк зис (что-то типа этого):
$this->Post->contain('Tag');$this->Post->find('all');
Или вот так:
$this->Post->find('all', array('contain' => 'Tag'));
Результат таких строк вполне предсказуем :)
Теперь нам нужно отфильтровать данные связанных моделей.
Для примера мы выбираем только авторов комментариев:
$this->Post->contain('Comment.author');$this->Post->find('all');//or..$this->Post->find('all', array('contain' => 'Comment.author'));
В результате получаем список постов и авторов, которые его прокомментировали:
[0] => Array([Post] => Array([id] => 1[title] => First article[content] => aaa[created] => 2008-05-18 00:00:00)[Comment] => Array([0] => Array([author] => Daniel[post_id] => 1)[1] => Array([author] => Sam[post_id] => 1)))[1] => Array(...
Авторы CakePHP отметили также, что Pramary Key основной модели по базе (для постов – post_id) используется в служебных целях для связи комментов с постами, поэтому он будет всегда в списке.
А теперь пример с поиском по связанным моделям:
$this->Post->contain('Comment.author = "Daniel"');$this->Post->find('all');//or...$this->Post->find('all', array('contain' => 'Comment.author = "Daniel"'));
Дешевый и сердитый вариан поиска покажет посты, которые прокомментировал Daniel:
[0] => Array([Post] => Array([id] => 1[title] => First article[content] => aaa[created] => 2008-05-18 00:00:00)[Comment] => Array([0] => Array([id] => 1[post_id] => 1[author] => Daniel[email] => dan@example.com[website] => http://example.com[comment] => First comment[created] => 2008-05-18 00:00:00)))
Дополнительные фильтры выборок доступны в стандартных параметрах Model->find():
$this->Post->find('all', array('contain' => array('Comment' => array('conditions' => array('Comment.author =' => "Daniel"),'order' => 'Comment.created DESC'))));
Полезный аддон, верно?
About