У меня есть серия моделей Post, в которых есть модели AndEndBelongsToMany Media. В некоторых вызовах функций внутри модели Post мне не нужно извлекать весь список моделей мультимедиа. Однако, когда я использую следующий код:
$this->unbindModel( array('hasAndBelongsToMany' => array('Media')) ); // Rebind to get only the fields we need: $this->bindModel( array('hasAndBelongsToMany' => array( 'Media' => array( 'className' => 'Media', 'joinTable' => 'media_posts', 'foreignKey' => 'post_id', 'associationForeignKey' => 'media_id', 'limit' => 1, 'fields' => array('Media.type', 'Media.path', 'Media.title') ) ) ) ); $this->find('all', $params);
Этот предел работает только на одной из первой модели Post Post, и все следующие модели Post не имеют связанных носителей:
Array ( [0] => Array ( [Profile] => Array ( ) [Media] => Array ( [0] => Array ( [type] => photo [path] => '' [title] => '' ) ) ) [1] => Array ( [Profile] => Array ( ) [Media] => Array ( ) ) )
Любые предложения были бы замечательными. Благодаря!
почему бы не использовать сдерживаемое поведение
// you would probably want the next line in the app_model ot be able to use it with all models $this->Post->actsAs = array('Containable') $params['conditions'] = array( ); $params['contain'] = array( 'Media' => array( 'fields' => array( 'type', 'path', 'title' ), 'limit' => 1 ) ); $this->Post->find('all', $params);
Просто попробовал это и получил этот sql (Module <-> Tag):
SELECT `Module`.`id` FROM `modules` AS `Module` WHERE 1 = 1
а также
SELECT `Tag`.`id`, `ModulesTag`.`module_id`, `ModulesTag`.`tag_id` FROM `tags` AS `Tag` JOIN `modules_tags` AS `ModulesTag` ON (`ModulesTag`.`module_id` IN (1, 2, 3, 4) AND `ModulesTag`.`tag_id` = `Tag`.`id`) WHERE `Tag`.`belongs_to` = 'Module' ORDER BY `Tag`.`name` ASC LIMIT 1
очевидно, что не может вернуть желаемый результат, так как вам придется делать запрос для каждого результата модуля (что опять-таки приведет к слишком большому числу запросов).
В качестве вывода я бы вернул все теги (в моем примере), поскольку накладные расходы в слишком большом количестве строк результатов лучше, чем накладные расходы слишком большого количества запросов.
Cake извлекает все связанные с Habtm записи в одном пакетном запросе, а затем собирает их в массив результатов впоследствии. Любые дополнительные условия, которые вы укажете в ассоциации, будут использоваться как в запросе, так что это будет выглядеть примерно так:
SELECT … FROM Media WHERE Media.id in (1, 2, 3, …) LIMIT 1
Таким образом, он будет извлекать только одну модель HABTM.
Для этого нет простого решения. Возможно, вы могли бы снова подумать об исходной предпосылке и почему первая запись ( LIMIT 1
), предположительно, правильная, возможно, вы можете найти другое условие для запроса.
В противном случае вы можете перестроить свои модели, чтобы Media hasMany
отношение medias_posts
к medias_posts
, сводной таблице. Для hasMany и принадлежит к запросам, Cake автоматически выполняет JOIN
запросы. Тогда вы можете использовать предложение GROUP BY
, которое даст вам желаемый результат:
SELECT … FROM Media JOIN medias_posts … GROUP BY medias_posts.post_id
Возможно, вам также захочется поэкспериментировать с передачей параметра 'join'
с запросом, чтобы добиться этого эффекта без обширного перепроверки.
$this->Media->find('all', array('join' => array(…), …));
Попробуй это:
$this->yourModel->hasAndBelongsToMany['Media'] = false; // or null
А затем установите свою ассоциацию HABTM вручную
$this->yourModel->hasAndBelongsToMany['Media'] = array(........);
Или просто измените ассоциацию, не опуская ее:
$this->yourModel->HABTM['Media']['fields'] = array(....)
CakePHP имеет очень мощный инструмент для этого сдерживаемого поведения