Связь Cakephp habtm не может правильно фильтроваться по тегу

У меня есть отношение habtm между пользователями и тегами. Однако это работает так, что наш список тегов поддерживается отдельно от пользователей. Такие, которые говорят, что в настоящее время существует ровно 12 тегов и N пользователей. По мере добавления, добавления и удаления новых пользователей количество тегов не изменится, но количество записей в таблице taggeds_users будет увеличиваться, чтобы точно отражать теги всех пользователей. Эта часть работает.

Кроме того, существует интерфейс, который позволяет пользователям фильтровать отмеченных пользователей по их тегам. Этот интерфейс разработан таким образом, что если у пользователя A есть теги Monday и Tuesday, они будут отображаться в поиске по любому из них. Кроме того, если пользователь B имеет теги Monday и Wednesday и предварительно выполняется поиск для поиска пользователей, которые включают тег Monday и исключают тег Wednesday, тогда пользователь B не должен отображаться (исключения превосходят включения).

Cake может управлять требованием включения тегов в поиск, и отдельно Cake может управлять требованием исключения тегов. Проблема заключается в том, чтобы заставить Cakephp «знать», что, когда пользователь C имеет теги X и Z, и выполняется поиск запрошенных пользователей, включая тег X и исключая тег Z, этот пользователь C НЕ должен появляться. В настоящее время пользователь C действительно появляется в результатах.

Я понимаю, что это результат операции соединения, которую необходимо выполнить в БД. т. е. поскольку у пользователя C есть два тега, у этого пользователя также есть две записи, возвращенные из БД. Cake правильно игнорирует один, но другой имеет правильный тег и позволяет пользователю C вводить наборы результатов, которые не предназначены для этого пользователя. Есть ли способ заставить торт решить эту проблему. Я могу исправить это на сервере (удалить пользователя C в контроллере, но я чувствую, что упускаю что-то простое). Это запрос, который привлекает внимание пользователей к тегам:

$conditions = array(
    'AND' => array(
        'Tagging.tag_name' => array(
            (int) 0 => 'tech'
        ),
        'NOT' => array(
            'Tagging.tag_name' => array(
                (int) 0 => 'monday'
            )
        )
    )
);

// I am also using the join options to preform this search
$joins[] = array(
    'table'         =>  'taggings_users',
    'alias'         =>  'TaggingUser',
    'type'          =>  'inner',
    'conditions'    =>  array(
        'User.id = TaggingUser.user_id'
    )
);

$joins[] =  array(
    'table'         =>  'taggings',
    'alias'         =>  'Tagging',
    'type'          =>  'inner',
    'conditions'    =>  array(
        'TaggingUser.tagging_id = Tagging.id'
    )
);

// which powers this operation
$this->paginate = array( 'conditions' => $conditions, 'joins' => $joins, 'limit' => 50 );

// there are users in here that should not be
$users = $this->paginate('User');

// thank you to anyone who helps.

person usumoio    schedule 07.08.2013    source источник
comment
Я не понимаю, как это можно сделать без дополнительного выбора или фильтрации в вашем коде после первого набора результатов. Теги не находятся в одной и той же строке результатов (поскольку они находятся в таблице ссылок, в которой есть 1 тег на строку). Таким образом, тег X AND NOT Y всегда будет истинным для любой строки с тегом X. Если поле tag = X, это не может быть чем-то другим. Это похоже на состояние if name="bob" AND NOT name="sally".   -  person Costa    schedule 08.08.2013
comment
Подзапросы торта: book.cakephp.org /2.0/ru/модели/   -  person Costa    schedule 08.08.2013
comment
Лучше всего написать реальный рабочий запрос и опубликовать его, а затем просто выяснить, как его построить с соглашениями Cake. Вы обнаружите, что это гораздо проще понять, чем просто перейти прямо к Cake.   -  person Dave    schedule 31.08.2013
comment
Используете ли вы плагин тегов CakeDC? Я думаю, что у них есть собственный метод для такого рода вещей.   -  person baordog    schedule 11.09.2013


Ответы (1)


Без тестирования я думаю, что это сработает, когда вы добавите еще одно соединение:

$joins[] =  array(
    'table'         =>  'taggings',
    'alias'         =>  'Tagging2',
    'type'          =>  'inner',
    'conditions'    =>  array(
        'TaggingUser.tagging_id = Tagging2.id'
    )
);

Обратите внимание, что я изменил «alias» на «Tagged2». А потом

$conditions = array(
    'AND' => array(
        'Tagging.tag_name' => array(
            (int) 0 => 'tech'
        ),
        'NOT' => array(
            'Tagging2.tag_name' => array(
                (int) 0 => 'monday'
            )
        )
    )
);

Кроме того, я не думаю, что этот синтаксис "(int) 0" необходим. Достаточно написать

$conditions = array(
    'AND' => array(
        'Tagging.tag_name' => 'tech',
        'NOT' => array(
            'Tagging2.tag_name' => 'monday'
        )
    )
);
person Mark    schedule 22.10.2013