Index SiteMap Portfolio

Назад

июл
31

CakePHP Containable Behavior

Новым аддоном в ядре CakePHP является Containable Behavior (далее буду писать CB, для удобства). Это поведение модели используется для ограничений в выборках связанных моделей при вызове find-методов.

Другими словами: при использовании CB вы можете указать какие модели вам необходимы в массиве, который вернет find-метод. Кроме того, можно указать и список полей, который вас интересует в связанной модели. Этот класс также решает задачу поиска по данным связанных моделей.

Слишком обезображенный текст получается выше, поэтому лучше всего разбираться со всем вышесказанным на примерах.

Оригинал статьи от разработчиков CakePHP: Containable Behavior

Для использования CB необходимо выполнить стандартную процедуру: заполнить поле $actsAs в вашей модели:

  1. class Post extends AppModel {
  2. var $actsAs = array('Containable');
  3. }

Для подключения на лету используем метод attach():

  1. $this->Post->Behaviors->attach('Containable');

Итак, имеем пример модели Post, которая имеет много комментов (hasMany Comment), а также имеет много тегов и в тоже время пренадлежит многим тегам (hasAndBelongsToMany Tag). Стандартный вызов find() вернет примерно следующий результат:

  1. debug($this->Post->find('all'));
  2. [0] => Array
  3. (
  4. [Post] => Array
  5. (
  6. [id] => 1
  7. [title] => First article
  8. [content] => aaa
  9. [created] => 2008-05-18 00:00:00
  10. )
  11. [Comment] => Array
  12. (
  13. [0] => Array
  14. (
  15. [id] => 1
  16. [post_id] => 1
  17. [author] => Daniel
  18. [email] => dan@example.com
  19. [website] => http://example.com
  20. [comment] => First comment
  21. [created] => 2008-05-18 00:00:00
  22. )
  23. [1] => Array
  24. (
  25. [id] => 2
  26. [post_id] => 1
  27. [author] => Sam
  28. [email] => sam@example.net
  29. [website] => http://example.net
  30. [comment] => Second comment
  31. [created] => 2008-05-18 00:00:00
  32. )
  33. )
  34. [Tag] => Array
  35. (
  36. [0] => Array
  37. (
  38. [id] => 1
  39. [name] => A
  40. )
  41. [1] => Array
  42. (
  43. [id] => 2
  44. [name] => B
  45. )
  46. )
  47. )
  48. [1] => Array
  49. (
  50. [Post] => Array
  51. (...

Согласитесь, в большинстве случаев, вам не нужно столько данных в результате. Нужна помощь CB.

Чтобы получить только информацию о посте, используем следующую конструкцию:

  1. $this->Post->contain();
  2. $this->Post->find('all');

Также можно настроить выборку во втором параметре метода find():

  1. $this->Post->find('all', array('contain' => false));

Итого, имеем только наши модельки. Ничего личнего больше нет:

  1. [0] => Array
  2. (
  3. [Post] => Array
  4. (
  5. [id] => 1
  6. [title] => First article
  7. [content] => aaa
  8. [created] => 2008-05-18 00:00:00
  9. )
  10. )
  11. [1] => Array
  12. (
  13. [Post] => Array
  14. (
  15. [id] => 2
  16. [title] => Second article
  17. [content] => bbb
  18. [created] => 2008-05-19 00:00:00
  19. )
  20. )
Цитата:

This sort of help isn't new: in fact, you can do that without the ContainableBehavior doing something like this:

  1. $this->Post->recursive = -1;
  2. $this->Post->find('all');
В переводе означает, что ничего нового до этой строки мы не нашли. Трудно не согласиться :) Поле recursive говорит о том, до какого уровня вложенности выбирать связанные модели. Значение -1 скажет модели, что нужна только она.

А вот теперь примеры по делу. Нужно выбрать посты только с тегами, без комментариев. Recursive здесь никак не поможет. Делаем энифинк лайк зис (что-то типа этого):

  1. $this->Post->contain('Tag');
  2. $this->Post->find('all');

Или вот так:

  1. $this->Post->find('all', array('contain' => 'Tag'));
Результат таких строк вполне предсказуем :)

Теперь нам нужно отфильтровать данные связанных моделей. Для примера мы выбираем только авторов комментариев:

  1. $this->Post->contain('Comment.author');
  2. $this->Post->find('all');
  3. //or..
  4. $this->Post->find('all', array('contain' => 'Comment.author'));

В результате получаем список постов и авторов, которые его прокомментировали:

  1. [0] => Array
  2. (
  3. [Post] => Array
  4. (
  5. [id] => 1
  6. [title] => First article
  7. [content] => aaa
  8. [created] => 2008-05-18 00:00:00
  9. )
  10. [Comment] => Array
  11. (
  12. [0] => Array
  13. (
  14. [author] => Daniel
  15. [post_id] => 1
  16. )
  17. [1] => Array
  18. (
  19. [author] => Sam
  20. [post_id] => 1
  21. )
  22. )
  23. )
  24. [1] => Array
  25. (...

Авторы CakePHP отметили также, что Pramary Key основной модели по базе (для постов - post_id) используется в служебных целях для связи комментов с постами, поэтому он будет всегда в списке.

А теперь пример с поиском по связанным моделям:

  1. $this->Post->contain('Comment.author = "Daniel"');
  2. $this->Post->find('all');
  3. //or...
  4. $this->Post->find('all', array('contain' => 'Comment.author = "Daniel"'));

Дешевый и сердитый вариан поиска покажет посты, которые прокомментировал Daniel:

  1. [0] => Array
  2. (
  3. [Post] => Array
  4. (
  5. [id] => 1
  6. [title] => First article
  7. [content] => aaa
  8. [created] => 2008-05-18 00:00:00
  9. )
  10. [Comment] => Array
  11. (
  12. [0] => Array
  13. (
  14. [id] => 1
  15. [post_id] => 1
  16. [author] => Daniel
  17. [email] => dan@example.com
  18. [website] => http://example.com
  19. [comment] => First comment
  20. [created] => 2008-05-18 00:00:00
  21. )
  22. )
  23. )

Дополнительные фильтры выборок доступны в стандартных параметрах Model->find():

  1. $this->Post->find('all', array('contain' => array(
  2. 'Comment' => array(
  3. 'conditions' => array('Comment.author =' => "Daniel"),
  4. 'order' => 'Comment.created DESC'
  5. )
  6. )));

Полезный аддон, верно?

Добавить в закладки на google.com Добавить в закладки на bobrdobr.ru Добавить в закладки на del.icio.us Добавить в закладки на technorati.com Добавить в закладки на linkstore.ru Добавить в закладки на news2.ru Добавить в закладки на rumarkz.ru Добавить в закладки на memori.ru Добавить в закладки на moemesto.ru

Ваше мнение

* Имя:
* E-mail:
*Этот адрес не публикуется. Для общих контаков оставляйте адрес в комментарии.
Сайт/Блог:
Примечание. Комментарии находятся в теге <noindex>, что значит: смысла срать здесь нет.
Добавить в закладки на google.com Добавить в закладки на bobrdobr.ru Добавить в закладки на del.icio.us Добавить в закладки на technorati.com Добавить в закладки на linkstore.ru Добавить в закладки на rumarkz.ru Добавить в закладки на memori.ru Добавить в закладки на moemesto.ru

 Бесплатно

Читать мою ленту
Получать RSS-ленту на почту



Хостинг предоставлен компанией
TutHost.com