То, что вы пытаетесь сделать, в значительной степени встроено в CakePHP.Главное, чтобы ваши модели были правильно связаны.Как только это будет выполнено, Cake выполнит большую часть тяжелой работы за вас.
Для вашей ситуации используйте 3 связанные модели:
class Story extends AppModel{
var $belongsTo = 'Author';
var $hasMany = 'Comment';
}
class Author extends AppModel{
var $hasMany = array( 'Story', 'Comment' );
var $hasAndBelongsToMany = 'User';
}
class Comment extends AppModel{
var $belongsTo = array( 'Author', 'Story' );
}
Настройте ваши столы в соответствии с Cakeконвенций.Затем небольшое волшебство CakePHP в вашем контроллере:
$this->Story->Author->bindModel( array( 'hasOne' => array( 'AuthorsUsers' ) ) );
$myAuthors = $this->Story->Author->find( 'list', array(
'fields' => array( 'id' ),
'conditions' => array( 'AuthorsUsers.user_id' => $userId ),
'recursive' => false
) );
$stories = $this->Story->find( 'all', array(
'fields' => array( 'Story.id', 'Story.title', 'Author.id', 'Author.name' ),
'order' => 'published_date DESC',
'conditions' => array( 'Author.id' => $myAuthors ),
'recursive' => 2
) );
Краткое объяснение происходящего:
bindModel()
позволяет Cake знать, что вы хотитеиспользуйте ассоциацию HABTM для поиска авторов по связанному идентификатору пользователя.(Соглашение Cake заключается в том, что для присоединения к ассоциации Author-> User HABTM имеется таблица с именем «author_users».) - Если вы отладите переменную
$myAuthors
, вы увидите, что она получает простой массив идентификаторов. 'conditions' => array( 'field' => array() )
будет обработан как "ГДЕ поле IN (...)".В этом примере мы получаем все модели WHERE 'Author.id' IN $myAuthors
. - Короткий вызов
$this->Story->find()
- это красота Cake.Он автоматически найдет все модели Story, соответствующие указанным условиям, и , а также найдет другие модели, связанные с каждой найденной Story.(Вы можете запретить поиск связанных моделей, отключив Recursive или используя Containable поведение.) - Отладка переменной
$stories
покажет вам структуру, подобнуюследующее:
Array
(
[0] => Array
(
[Story] => Array
(
[id] => 1
[title] => 'Common Sense'
[published_date] => 1776-01-10
)
[Author] => Array
(
[id] => 1
[name] => 'Thomas Paine'
)
[Comment] => Array
(
[0] => Array
(
[id] => 1
[text] => 'Revolutionary!'
[Author] => Array
(
[id] => 3
[name] => 'Silence Dogood'
)
)
[1...n] => ...
)
)
[1...n] => ...
)
Затем вы можете использовать эту структуру в своем представлении для отображения данных по вашему желанию.
У меня такое чувство, что должен быть способ сделать это столько 1 запрос, но этот способ работает и не требует от вас выполнения каких-либо подзапросов или вставки пользовательского SQL в ваш вызов Cake find()
.