CakePHP найти HABTM
У меня 3 модели (User
, Message
а также Tag
) со следующими отношениями:
User
имеет многоMessage
Message
принадлежитUser
Message
HABTMTag
Tag
HABTMMessage
Если пользователь вошел в систему, он может захотеть увидеть все Message
помечен чем-то.
$messages = $this->Message->find('all', array(
'conditions' => array("Message.user_id" => $this->uid),
'contain' => array(
'Tag' => array(
'conditions' => array(
'Tag.id' => $activetag['Tag']['id']
)
)
));
Однако эта находка вернет ВСЕ сообщения этого пользователя. (Контейнерное поведение включено в обе модели)
2 ответа
Содержимое на дочернем элементе (тег) не выполняет фильтрацию на родительском элементе (сообщение), поэтому все сообщения возвращаются. Содержимое только помещает условие на сам тег, в вашем случае сообщения, не соответствующие $activeTag, будут по-прежнему возвращаться, но с прикрепленным пустым массивом тегов, в то время как сопоставление сообщений будет возвращаться с массивом, содержащим только один тег, $activeTag, но все сообщения вернется.
Для вашей цели CakepHP рекомендует использовать функцию соединения для фильтрации с HABTM, он автоматически присоединяет вас к hasOne или ownTo, но когда дело доходит до HABTM, вам может понадобиться выполнить соединение самостоятельно, если это необходимо.
при условии, что таблицы названы условно:
$this->Message->recursive = -1;
$options['joins'] = array(
array('table' => 'messages_tags',
'alias' => 'MessageTag',
'type' => 'INNER',
'conditions' => array(
'Message.id = MessageTag.message_id',
)
) );
$options['conditions'] = array(
'MessageTag.tag_id' => $activetag['Tag']['id'],
'Message.user_id' => $this->uid );
$message = $this->Message->find('all', $options);
дополнительная информация здесь: http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html
В вашем модельном сообщении добавьте
**
* @see Model::$actsAs
*/
public $actsAs = array(
'Containable',
);
/**
* @see Model::$belongsTo
*/
public $belongsTo = array(
'Message' => array(
'className' => 'Message',
'foreignKey' => 'message_id',
),
'Tags' => array(
'className' => 'Tag',
'foreignKey' => 'tag_id',
),
);
в вашем контроллере:
// $tagsId = tags ids
$message = $this->MessageTag->find('all', array('conditions' => array('MessageTag.tag_id' => $tagsId),'contain' => array('Message')));
также лучше следовать соглашению об именах тортов, если у вас есть теги (множественное число), message_tags(первое единственное число, второе множественное число), таблицы сообщений (множественное число), у вас должны быть Tag,MessageTag,Message Models.