【问题标题】:HABTM Find with CakePHP 2.0使用 CakePHP 2.0 查找 HABTM
【发布时间】:2013-03-10 07:05:11
【问题描述】:

我正在尝试进行搜索,对具有特定标签或标签的帖子使用分页(例如,如果用户要选择两个标签,则将返回包含任一标签的帖子)。

我在我的帖子表中定义了关系

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

如何使用 Find 检索具有给定标签的行(名称或 ID 都可以)

尝试:

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

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

查看调试信息,这些表似乎没有加入 Posts_Tags 和 Tags 表,但是,当我将数据调试到视图时,Posts 对象包含标签数据。

我能找到的大部分文档似乎都围绕着早期版本的 CakePHP,我们将不胜感激。

【问题讨论】:

  • 将外键名称检查到相关表中。
  • 表的架构如下: CREATE TABLE posts_tags ( id int(10) unsigned NOT NULL AUTO_INCREMENT, post_id int(10) unsigned NOT NULL, tag_id int (10)无符号非空,主键(id),键post_tags_post_id_fkpost_id),键post_tags_tag_id_fktag_id),约束post_tags_post_id_fk外键(post_id)3345参考@9876 (id) ON DELETE CASCADE ON UPDATE CASCADE, 约束post_tags_tag_id_fk FOREIGN KEY (tag_id) 参考tags (id) ON DELETE CASCADE ON UPDATE CASCADE);

标签: cakephp cakephp-2.0


【解决方案1】:

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

创建一个名为 HabtmBehavior.php 的文件并将其放入您的 app/Model/Behavior 文件夹中。 将代码块放在那里并保存文件。

将行为添加到您的模型中:例如 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;
    }

}

希望这会有所帮助。 祝您烘焙愉快。

【讨论】:

    【解决方案2】:

    我认为最好的解决方案是在连接表模型上应用查找功能。我以前试过这个,效果很好。

    在您的 PostTag 模型中:

    /**
     * @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',
            ),
        );
    

    在您的控制器中:

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

    如果你有标签(复数),post_tags(第一单数第二复数),posts(复数)表,你必须有标签,邮政标签,邮政模型。

    【讨论】:

      猜你喜欢
      • 2011-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-05
      相关资源
      最近更新 更多