Как мне запрашивать данные в CakePHP, используя отношения HABTM?

Я работаю над приложением CakePHP 1.2. У меня есть модель «Пользователь», определенная с помощью нескольких отношений HABTM с другими таблицами через таблицу соединений.

Теперь мне поручено найти информацию о пользователях на основе данных, хранящихся в одной из этих таблиц HABTM. К сожалению, при выполнении запроса мое условие отклоняется с ошибкой об отсутствующей таблице. При осмотре кажется, что CakePHP не включает ни одну из таблиц HABTM в оператор select.

Отношения My User HABTM следующие:

    var $hasAndBelongsToMany = array(
    'Course' => array(
        'className'             => 'Course',
        'joinTable'              => 'course_members',
        'foreignKey'             => 'user_id',
        'associationForeignKey'  => 'course_id',
        'conditions'             => '',
        'order'                  => '',
        'limit'                  => '',
        'uniq'                   => false,
        'finderQuery'            => '',
        'deleteQuery'            => '',
        'insertQuery'            => ''
    ),
    'School' => array(
        'className'             => 'School',
        'joinTable'              => 'school_members',
        'foreignKey'             => 'user_id',
        'associationForeignKey'  => 'school_id',
        'conditions'             => '',
        'order'                  => '',
        'limit'                  => '',
        'uniq'                   => false,
        'finderQuery'            => '',
        'deleteQuery'            => '',
        'insertQuery'            => ''
    ),
    'Team' => array(
        'className'             => 'Team',
        'joinTable'              => 'team_members',
        'foreignKey'             => 'user_id',
        'associationForeignKey'  => 'team_id',
        'conditions'             => '',
        'order'                  => '',
        'limit'                  => '',
        'uniq'                   => false,
        'finderQuery'            => '',
        'deleteQuery'            => '',
        'insertQuery'            => ''
    )
);

Ошибка:

Ошибка SQL: 1054: неизвестный столбец 'School.name' в 'where clause'

И, наконец, запрос, который он пытается выполнить

     SELECT 
 `User`.`id`, `User`.`username`, `User`.`password`, `User`.`firstName`, `User`.`lastName`, `User`.`email

`, `User`.`phone`, `User`.`streetAddress`, `User`.`city`, `User`.`province`, `User`.`country`, `User

`.`postal`, `User`.`userlevel`, `User`.`modified`, `User`.`created`, `User`.`deleted`, `User`.`deleted_date

` FROM `users` AS `User`   WHERE `User`.`id` = 6 AND `School`.`name` LIKE '%Test%'    LIMIT 1

person Community    schedule 29.11.2008    source источник


Ответы (4)


Увеличьте уровень отладки до 2 и посмотрите на вывод SQL. Найдите запрос, который генерирует ваш код, и вы заметите, что их несколько. Уровень ORM в CakePHP не присоединяется к таблицам, связанным с HABTM, в первом запросе. Он получает результаты от первого выбора, а затем отдельно выбирает данные HABTM для каждого элемента. Поскольку объединяемая таблица не входит в первый запрос, ваше условие, которое предназначено для использования в объединенной таблице, приводит к ошибке, которую вы видите.

В кулинарной книге есть раздел, посвященный HABTM. ассоциации и получение данных на основе условий в таблице HABTM, которые соответствуют вашим требованиям.

person neilcrookes    schedule 30.11.2008

Из Поваренной книги: http://book.cakephp.org/view/83/hasAndBelongsToMany-HABTM

Один из вариантов - поиск по модели тегов (вместо рецепта), который также даст нам все связанные рецепты.

$this->Recipe->Tag->find('all', array(
    'conditions' => array('Tag.name' => 'Dessert')));

Мы также могли бы использовать модель таблицы соединений (которую предоставляет нам CakePHP) для поиска заданного идентификатора.

$this->Recipe->bindModel(array('hasOne' => array('RecipesTag')));
$this->Recipe->find('all', array(
    'fields' => array('Recipe.*'),
    'conditions' => array('RecipesTag.tag_id' => 124) // id of Dessert
));

Также можно создать экзотическую ассоциацию с целью создания необходимого количества объединений для фильтрации, например:

$this->Recipe->bindModel(array('hasOne' => array('RecipesTag',
    'FilterTag' => array(
        'className' => 'Tag',
        'foreignKey' => false,
        'conditions' => array('FilterTag.id = RecipesTag.tag_id')
))));
$this->Recipe->find('all', array(
    'fields' => array('Recipe.*'),
    'conditions' => array('FilterTag.name' => 'Dessert')
));
person Asif Zardari    schedule 07.08.2010
comment
Я считаю, что это был лучший ответ - нужно учитывать, что вы должны убедиться, что в модели, которую вы связали, есть использование «find». Так что 'contain' = ›'FilterTag' после ваших условий. - person TeckniX; 05.01.2013

Ваша таблица должна называться "school_users", а не "school_members", потому что она используется для связи многие ко многим, поэтому использование формы множественного числа в имени таблицы с обеих сторон является уместным.

Вы также устанавливаете Model ClassName "School" как псевдоним для HABTM. Вы должны изменить это на что-то более общее, например «Школы» или «Пользователь входит и имеет много школ», чтобы избежать конфликтов.

И еще один совет: попробуйте найти пользователя «через» Модель школы, а не Модель пользователя.

$ this-> Пользователь-> Школы-> найти ()

Надеюсь это поможет.

person m3nt0r    schedule 05.12.2008

FWIW, ваши таблицы соединения кажутся "странно названными", поскольку они не следуют соглашению, описанному здесь:

http://book.cakephp.org/view/83/hasAndBelongsToMany-HABTM

В любом случае, удачи, я помню, как HABTM был занудой в CakePHP.

person J Cooper    schedule 29.11.2008
comment
Насколько мне известно, это не имеет значения, поскольку я явно задаю имена объединенной таблицы и модели. - person ; 29.11.2008