Как я могу запрашивать данные в CakePHP, используя отношения HABTM? - PullRequest
7 голосов
/ 29 ноября 2008

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

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

Мой пользователь 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

Ответы [ 4 ]

7 голосов
/ 30 ноября 2008

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

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

5 голосов
/ 07 августа 2010

Из поваренной книги: 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')
));
2 голосов
/ 05 декабря 2008

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

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

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

$ this-> User-> Schools-> найти ()

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

0 голосов
/ 29 ноября 2008

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

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

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

...