CakePHP: использование глубоких ассоциаций моделей 2-го уровня в состоянии «найти», возвращая дублированные результаты - PullRequest
0 голосов
/ 08 февраля 2012

Я прочитал множество постов, часами просматривал документы на cakephp.org и даже пробовал различные практические примеры, и я не могу понять, что это правильно. У меня есть 3 таблицы следующим образом:

  • Проекты
  • project_tags
  • метка

Когда кто-то добавляет новый проект, он выбирает свои теги, которые выбираются из предопределенного списка в таблице тегов. Введенный ими тег сохраняется в project_tags с использованием полей project_id и tag_id.

Типовые отношения следующие:

  • Проект имеет много проектовTag
  • projectTag принадлежит проекту
  • ProjectTag принадлежит тегу

Имею ли я правильные отношения, все еще тривиально для меня, но я попробовал здесь множество возможностей.

То, что я пытаюсь сделать, это выполнить поиск по всем проектам определенного тега. Я сделал это, выполнив следующее:

$this->Project->contain(array('ProjectTag' => 'Tag', 'User' => array('id')));
$projects = $this->Project->find('all', array('conditions' => array('ProjectTag.tag_id' => '6')));

Результатом является ошибка SQL, что столбец ProjectTag.tag_id не существует. Это говорит мне, что в ассоциации есть ошибка, но где?

Это из-за того, что я не могу использовать модель hasMany 2-го уровня с глубокими связями в моем состоянии при использовании встраиваемого? Если так, как я могу это исправить?

Я знаю, это долго, извините. Кто-нибудь может пролить свет на эту странную ситуацию?

Другим подходом, который я попробовал, было использование unbindModel () в Project, удаление всех привязок к ProjectTag, а затем добавление hasOne с использованием bindModel () и условие ProjectTag.project_id = Project.id, но это привело к 4 записям возвращается один и тот же проект, по одному на каждый ProjectTag, что не кажется правильным.

Я использую сдерживаемое поведение и установил recursive = -1 в AppModel.

Любая помощь очень ценится. Спасибо

Ответы [ 2 ]

2 голосов
/ 09 февраля 2012

проблема в том, что вы ошиблись в отношениях в моделях. В идеале ваш случай - это отношения hasAndBelongsToMany.

Проект имеет теги AndBelongsToMany Tag hasAndBelongsToMany Proyect

Это естественная связь в данном случае. Таблица ProjectTag - это только промежуточная таблица, а не модель в CakePHP.

для получения дополнительной информации: http://book.cakephp.org/1.3/view/1044/hasAndBelongsToMany-HABTM

1 голос
/ 14 февраля 2012

Для всех, кто может наткнуться на этот пост, попытка включить в свой запрос find или paginate модели, имеющие более 2 уровней глубины, не является простой задачей, если не сказать больше.

Пункт номер один, который продолжал подниматься, заключался в том, что CakePHP выполняет отдельные запросы для каждой ассоциации hasMany и hasAndBelongsToMany, что делает практически невозможным включение их в условия поиска.

Мне представили 2x решения:

1) Создание пользовательского типа запроса

2) Используйте функции unbindModel и bindModel и заново создайте ассоциации как hasOne

Я выбрал пункт 2, потому что пункт 1 казался сомнительным, когда я читал документы (и это было рекомендовано только в качестве крайней меры), и это позволило мне изменить ассоциацию на лету, а затем сбросить ее, продолжая весело с ассоциациями как я и предполагал.

Для тех, кому интересно, у меня был модельный проект, у которого есть много ProjectTag, который принадлежит тегу. Было невозможно использовать Tag или ProjectTag в моих типах поиска, поэтому я сделал следующее:

Я использовал метод unbindModel () в Project, ProjectTag и Tag, удаляя все их ассоциации, по сути, освобождая все связи.

Затем я применил bindModel () к Project, ProjectTag и Tag. Наиболее важным был порядок (иерархия), в котором я применил эти обозначения, потому что я использовал свойство 'condition', которое позволило мне связать модель 'A' с моделью B, используя условия SQL WHERE. Например:

$this->Project->ProjectTag->unbindModel(array(
'belongsTo' => array('Tag')
));

$this->Project->unbindModel(array('hasMany' => array('ProjectTag')));

$this->Project->bindModel(array('hasOne' => array('ProjectTag' => array('foreignKey' => false, 'conditions' => array('ProjectTag.project_id = Project.id')))));

$this->Project->bindModel(array('hasOne' => array('Tag' => array('foreignKey' => false, 'conditions' => array('Tag.id = ProjectTag.tag_id')))));

Теперь мы можем использовать Tag.id так, как будто он имеет отношение hasOne к Project, что позволяет нам применять условия поиска непосредственно к тегу при возврате связанных проектов.

НЕОБХОДИМО, чтобы вы связали все отношения, которые используются в рассматриваемых моделях, иначе они порвутся.

Надеюсь, это поможет тем, кто сталкивается с той же проблемой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...