find() на основе условий в нескольких отношениях HABTM
Я работаю с CakePHP 2.1
Допустим, у меня есть следующие модели и отношения:Posts
принадлежит Edition
Posts
HABTM Editors
Posts
HABTM Tags
Я рассуждаю из PostsController
и я хотел бы найти все Posts
принадлежность к определенному Edition
и что Editor.id=55
связано и Tag.id=33
относится.
Я нашел много примеров, где найти Posts
основанный на условии, касающемся отношения HABTM, выполняется путем "обращения" направления и причины поиска из Editor
,
$this->Editor->find('all',
array(
'conditions'=>array('Editor.id'=>55),
'contain'=>array('Post')
)
);
К сожалению, здесь это не работает, потому что есть несколько отношений HABTM, на которые я хотел бы поставить условие.
Также используя contain
не работает так как отрубает только ветку (editors
) но не помогает отфильтровать его родитель (posts
).
Как мне это решить?
Может быть, мне нужно прибегнуть к специальным соединениям? И если так, может кто-нибудь объяснить мне, какой подход выбрать?
Редактировать: некоторый псевдокод, чтобы проиллюстрировать, чего я хочу достичь:
$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',
)
)
);
С уважением, Барт
Изменить решение: Следуя @RichardAtHome, я создал решение ниже. Не (пока) не применялось несколько условий соединения, но в этом не было необходимости:
// 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
);
2 ответа
Для этого типа запроса я обычно нахожу, что самому проще создавать объединения, так как торт не будет объединяться, вместо этого он выполнит несколько запросов (выберите подходящие строки из таблицы a, а затем извлеките соответствующие строки из таблицы b).
Ваш запрос должен выглядеть примерно так:
$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
)
)
)
)
);
Проверьте выводимый SQL, чтобы увидеть, что на самом деле делает этот запрос.
Пытаться:
$this->Post->find('all',
array('conditions'=>array(
'Edition.id'=>4,
'Editor.id' => '55',
'Tag.id' => '33',
)
)
);