2012-08-27 66 views
1

我正在尝试使用具有特定标记或标记的帖子使用分页(例如,如果用户选择了两个标记,则会返回包含任一标记的帖子)。HABTM Find with CakePHP 2.0

我有我的帖子表中定义的关系

public $hasAndBelongsToMany = array('Tags' => array(
      'className'    => 'Tags', 
      'joinTable'    => 'posts_tags', 
      'foreignKey'    => 'post_id', 
      'associationForeignKey' => 'tag_id', 
      'unique'     => 'keepExisting')); 

如何使用搜索来检索与给定的标签行(名称或ID,将被罚款)

尝试:

// other pagination settings goes here 
$this->paginate['conditions']['Tags.id'] = 13; 

给我一个关系不存在的错误。

看着调试信息,看起来表格没有加入Posts_Tags和Tags表格,但是当我调试数据到视图时,Posts对象包含标签数据。

我可以找到的大部分文档似乎都围绕着早期版本的CakePHP,希望有任何帮助。

+0

检查外键名到您的相关表中。 –

+0

该表的模式如下: CREATE TABLE'posts_tags'( 'id' int(10)unsigned NOT NULL AUTO_INCREMENT, 'post_id' int(10)unsigned NOT NULL, 'tag_id' int(10)无符号NOT NULL, PRIMARY KEY('id'), KEY'post_tags_post_id_fk'('post_id'), KEY'post_tags_tag_id_fk'('tag_id'), 约束'post_tags_post_id_fk'外键('post_id')参考'职位('''')在DELETE CASCADE ON UPDATE CASCADE上执行, CONSTRAINT'post_tags_tag_id_fk' FOREIGN KEY('tag_id')REFERENCES'tags'('id')ON DELETE CASCADE ON UPDATE CASCADE ); – user1627061

回答

1

我认为最好的解决方案是在连接表模型上应用find函数。我之前尝试过,它工作正常。

/** 
* @see Model::$actsAs 
*/ 
    public $actsAs = array(
     'Containable', 
    ); 

/** 
* @see Model::$belongsTo 
*/ 
    public $belongsTo = array(
     'Post' => array(
      'className' => 'Post', 
      'foreignKey' => 'post_id', 
     ), 
     'Tags' => array(
      'className' => 'Tag', 
      'foreignKey' => 'tag_id', 
     ), 
    ); 
在你的控制器

在PostTag模型

// $tagsId = tags ids 
    $posts = $this->PostTag->find('all', array('conditions' => array('PostTag.tag_id' => $tagsId),'contain' => array('Post'))); 

也是更好的后续蛋糕命名约定,如果有标签(复数),post_tags(第1特异第二复数) ,帖子(复数)表,你必须有标签,邮政标签,邮政模型。

3

我自己找不到令人满意的解决方案。 我创建了一个行为来照顾这个。

创建一个名为HabtmBehavior.php的文件,并将其放入您的应用/模型/行为文件夹中。 将代码块放在那里并保存文件。

将行为添加到您的模型:例如public $ actsAs = array('Habtm');

以下是find的用法示例。

<?php $this->Entry->find('all', array('habtm'=>array('Tag'=>array('Tag.title'=>'value to find'))) ?> 

分页会是这个样子:

$this->paginate['Entry']['habtm']['Tag'] = array('Tag.title'=>'value to find'); 

您可以自由,只要你想用的habtm阵列中增加额外的型号名称添加尽可能多的关系。 (只是要小心不要使它复杂,因为这可能会开始减慢你的查找结果。)

<?php 
class HabtmBehavior extends ModelBehavior { 

    public function beforeFind(Model $model, $options) { 
    if (!isset($options['joins'])) { 
     $options['joins'] = array(); 
    } 
    if (!isset($options['habtm'])) { 
     return $options; 
    } 
    $habtm = $options['habtm']; 
    unset($options['habtm']); 

    foreach($habtm as $m => $scope){ 
     $assoc = $model->hasAndBelongsToMany[$m]; 
     $bind = "{$assoc['with']}.{$assoc['foreignKey']} = {$model->alias}.{$model->primaryKey}"; 

     $options['joins'][] = array(
      'table' => $assoc['joinTable'], 
      'alias' => $assoc['with'], 
      'type' => 'inner', 
      'foreignKey' => false, 
      'conditions'=> array($bind) 
    ); 

     $bind = $m.'.'.$model->{$m}->primaryKey.' = '; 
     $bind .= "{$assoc['with']}.{$assoc['associationForeignKey']}"; 

     $options['joins'][] = array(
      'table' => $model->{$m}->table, 
      'alias' => $m, 
      'type' => 'inner', 
      'foreignKey' => false, 
      'conditions'=> array($bind) + (array)$scope, 
    ); 
    } 
    return $options; 
    } 

} 

希望这有助于。 快乐烘烤。