CakePHP - найти условия с ассоциациями - PullRequest
3 голосов
/ 12 января 2012

У меня есть проблема с условиями поиска cakePHP. У меня есть модель Club, модель User и модель Post:

Клуб имеет много сообщений

Клуб HABTM Пользователь

По сути, моя таблица clubs_users также содержит дополнительные поля, такие как, скажем, 'limit' и 'diff', которые соответственно указывают максимальное количество сообщений, которые пользователь хочет отобразить, и возраст, которому разрешено быть этим сообщениям. Я хотел бы выбрать соответствующие сообщения для каждого клуба, связанного с данным пользователем. Я делаю что-то вроде этого

        $clubs = $this->Club->User->find('first', array(
        'conditions' => array('User.id' => $id),
        'contain' => array(
            'Club' => array(
                'fields' => array(
                    'id',
                    'name'
                ),
                'Post' => array(
                    'fields' => array(
                        'id',
                        'title',
                        'description',
                        'created',
                    ),
                    'order' => array('Post.created' => 'DESC'),
                    'conditions' => array(
                        'DATEDIFF(NOW(), `Post.created`) <= /* 1 */',
                    ),
                    'limit' => '/* 2 */'
                )
            )
        )
    ));

Что я должен поставить вместо 1 и 2, чтобы это работало? Я пробовал ClubsUser.diff и ClubsUser.limit, но получил сообщение об ошибке, заявив, что эти поля были неизвестны в предложении where.

Любая помощь будет приветствоваться.

Спасибо за чтение.

редактировать

После комментария Бансера я углубился в документ MySQL, и оказалось, что LIMIT ожидает только числовые аргументы. Поэтому я сейчас просто хочу вернуть посты, которые не слишком старые. Моя новая находка (с реальным именем поля)

$overview = $this->Club->Follower->find('first', array(
        'conditions' => array('Follower.id' => $this->Auth->user('id')),
        'contain' => array(
            'Club' => array(
                'fields' => array(
                    'id',
                    'name'
                ),
                'Post' => array(
                    'fields' => array(
                        'id',
                        'title',
                        'description',
                        'created',
                    ),
                    'order' => array('Post.created' => 'DESC'),
                    'conditions' => array(
                        'DATEDIFF(NOW(), `Post.created`) <= ClubsUser.max_time_posts',
                    ),
                    'limit' => 10
                )
            )
        )
    ));

Он генерирует три следующих SQL-запроса (для ясности я заменил имя поля на *):

SELECT * FROM `users` AS `Follower`
WHERE `Follower`.`id` = 1
LIMIT 1

SELECT * FROM `clubs` AS `Club`
JOIN `clubs_users` AS `ClubsUser`
ON (`ClubsUser`.`user_id` = 1 AND `ClubsUser`.`club_id` = `Club`.`id`)
ORDER BY `ClubsUser`.`role_id` DESC 

SELECT * FROM `posts` AS `Post`
WHERE DATEDIFF(NOW(), `Post`.`created`) <= `ClubsUser`.`max_time_posts` AND `Post`.`club_id` = (1)
ORDER BY `Post`.`created` DESC
LIMIT 10

Последний запрос возвращает ошибку: поле 'ClubsUser.max_time_posts' неизвестно в предложении where

В идеале я хотел бы получить запрос, близкий к приведенному ниже, вместо двух последних запросов:

SELECT * FROM `clubs` AS `Club`
JOIN `clubs_users` AS `ClubsUser`
ON (`ClubsUser`.`user_id` = 1 AND `ClubsUser`.`club_id` = `Club`.`id`)
LEFT JOIN `posts` AS `Post`
ON (`Post`.`club_id` = `Club`.`id` AND DATEDIFF(NOW(), `Post`.`created`) <= `ClubsUser`.`max_time_posts`) 
ORDER BY `ClubsUser`.`role_id` DESC, `Post`.`created` DESC
LIMIT 10

Есть идеи?

1 Ответ

2 голосов
/ 12 января 2012

Вы не должны использовать HABTM, если у вас есть дополнительные поля в таблице соединений, потому что Cake фактически удаляет и воссоздает эти объединения. Вы должны использовать ассоциацию "hasMany through":

Club hasMany ClubUser
User hasMany ClubUser
ClubUser belongsTo Club
ClubUser belongsTo User

Когда вы находите на User, вы просто используете ClubUser, а затем Club.

$this->User->find('all', array(
    'contain' => array(
        'ClubUser' => array(
            'fields' => array(
                'diff', 
                'limit'),
            'Club'))));

Подробнее здесь:

http://book.cakephp.org/1.3/view/1650/hasMany-through-The-Join-Model

и здесь:

http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasmany-through

...