Focus on IT Recommend

Home > has and belongs to many - CakePHP find HABTM

has and belongs to many - CakePHP find HABTM



I have 3 models (User, Message and Tag) with the following relations:

  • User hasMany Message
  • Message belongsto User
  • Message HABTM Tag
  • Tag HABTM Message

If a User is logged in he might want to see all Message tagged with something.

$messages = $this->Message->find('all', array(
    'conditions' => array("Message.user_id" => $this->uid),
    'contain' => array(
        'Tag' => array(
            'conditions' => array(
                '' => $activetag['Tag']['id']

However, this find will return ALL messages of that user. (Containable behaviour is included in both models)

cakephp has-and-belongs-to-many
  this question
edited Oct 18 '15 at 23:30 Oops D'oh 567 7 31 asked Feb 18 '13 at 22:16 Alex Schneider 132 2 14      Did you actually run this code or did you write it here? Because you must have gotten a syntax error whilst running this code: array('Tag' = array(...)) –  Jelmer Feb 18 '13 at 23:11      i did some changes, thats why there was that error -.- –  Alex Schneider Feb 18 '13 at 23:31


2 Answers

Containable on child (tag) does not perform filter on the parent (message), that's why all the messages are returned. The containable only place condition on the tag itself, in your case, messages not matching $activeTag would still get returned but with empty tag array attached, while messages matching would return with an array containing only one tag, the $activeTag, but all messages would get returned.

For your purpose CakepHP recommend using join function for filtering with HABTM, it joins hasOne or belongsTo for you automatically but when it comes to HABTM you may need to perform the join yourself if needed.

assuming tables are named conventionally:

$this->Message->recursive = -1;

$options['joins'] = array(
    array('table' => 'messages_tags',
        'alias' => 'MessageTag',
        'type' => 'INNER',
        'conditions' => array(
            ' = MessageTag.message_id',
    ) );

$options['conditions'] = array(
    'MessageTag.tag_id' => $activetag['Tag']['id'],
    'Message.user_id' => $this->uid );

$message = $this->Message->find('all', $options);

more info here:

Recommend:has and belongs to many - Cakephp retrieve data in HABTM association

BTM. Now here particular users are associated to distribution list, i wish to add more users, but when adding new users to distribution list, i would like to show users who are not associated with that distribution lists. what condition sho

  this answer
answered May 30 '13 at 1:44 Devon 23 4


In your Model Message add

 * @see Model::$actsAs
    public $actsAs = array(

 * @see Model::$belongsTo
    public $belongsTo = array(
        'Message' => array(
            'className' => 'Message',
            'foreignKey' => 'message_id',
        'Tags' => array(
            'className' => 'Tag',
            'foreignKey' => 'tag_id',

in your controller :

// $tagsId = tags ids
    $message = $this->MessageTag->find('all', array('conditions' => array('MessageTag.tag_id' => $tagsId),'contain' => array('Message')));

also is better follow cake naming convention, if you have tags(plural), message_tags(first singular second plural),messages(plural) tables you must have Tag,MessageTag,Message Models.

  this answer
answered Feb 18 '13 at 23:36 gounane 201 2 5


Recommend:has and belongs to many - CakePHP HABTM question

ree time. For starters I want to add multiple tags to multiple photos. I have a tags model and mot model (the photos). Snip of mot model: var $hasAndBelongsToMany = array( 'Tag' =>

------splitte line----------------------------