Frage

I'm working with CakePHP 2.1
Let's state I have the following models and relations:
Posts belongsTo Edition
Posts HABTM Editors
Posts HABTM Tags

I'm reasoning from the PostsController and I would like to find all Posts belonging to a certain Edition, and that Editor.id=55 is related and Tag.id=33 is related.

I have found many examples where finding Posts based on a condition over a HABTM relation is done by 'reversing' the find direction and reason from the Editor.

$this->Editor->find('all',
    array(
        'conditions'=>array('Editor.id'=>55),
        'contain'=>array('Post')
    )
);

Unfortunately this doesn't work here, because there are multiple HABTM relations that I would like to put a condition on.

Also using contain does not work since it only cuts off a branch (editors) but does not help filtering it's parent (posts).

How do I solve this?
Do I maybe need to resort to ad hoc joins? And if so, could someone explain me roughly what approach to take?

Edit: Some pseudo code in order to illustrate what I want to achieve:

$this->Post->find('all',
    array('conditions'=>array(
            'Edition.id'=>4,
             // start pseudo code
            'Post.Editor' => 'has at least one related editor with id=55',
            'Post.Tag' => 'has at least one related tag with id=33',
        )
    )
);

kind regards, Bart

Edit Solution: Following @RichardAtHome I created the solution below. Not (yet) employing multiple join conditions, but that appeared not to be necessary:

// Paginate over Cards that belong to current Subscription (belongsTo) AND the User is related to as an Editor (HABTM)
$this->paginate = array(
    'fields' => array('id','title','workingtitle','attachment_count','subscription_id'),
    'joins' => array(
        // create Editor-join
        array(
            'table' => 'cards_users',
            'alias' => 'Editor',
            'type' => 'left',
            'conditions' => array(
                'Editor.card_id = Card.id'
            )
        ), 
        array( 
            'table' => 'users', 
            'alias' => 'User', 
            'type' => 'left',
            'conditions'=> array( 
                'User.id = Editor.user_id'
            ) 
        )
    ),
    'conditions' => array(
        'OR' => array(
            // is Card in current subscription? (straightforward condition)
            array('Card.subscription_id',$subscription_id),
            // is current User assigned as Editor? (condition works with join above)
            array('User.id' => $user['id'])
        )
    ),
    'limit' => 10
);
War es hilfreich?

Lösung

For this type of query, I usually find it easiest to construct the joins myself as cake won't join, it will perform multiple queries instead (select matching rows from table a, then fetch matching rows from table b).

Your query needs to look something like this:

$this->Post->find('all',
    array(
        'conditions'=>array('Post.edition_id'=>4),
        'joins'=>array(
            array(
                'type'=>'inner',
                'table'=>'posts_editors',
                'alias'=>'PostsEditor',
                'conditions'=>array(
                    'PostsEditor.post_id = Post.id',
                    'PostsEditor.editor_id'=>55 // your criteia for editor id=55
                )
            ),
            array(
                'type'=>'inner',
                'table'='posts_tags',
                'alias'=>'PostsTag',
                'conditions'=>array(
                    'PostsTag.post_id = Post.id',
                    'PostsTag.tag_id'=>33 // your criteria for tag id = 33
                )

            )
        )
    )
);

Check the SQL that's output to see what this query is actually doing behind the scenes.

Andere Tipps

Try:

$this->Post->find('all',
        array('conditions'=>array(
                'Edition.id'=>4,
                'Editor.id' => '55',
                'Tag.id' => '33',
            )
        )
    );
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top