以前我依赖递归,但我没有得到一些解决方案,然后我发现 Containable 对这些工作正常。

我正在开发一个电影评论网站。因为我需要显示与特定类型相关的电影列表。

我有以下代码:

//example
$genre = "drama";

$options = array(
    'contain' => array(
        'Movie',
        'MoveiGenre.Genre' => array(
            'conditions' => array('MovieGenre.Genre.name = "'.$genre.'"')
        ),
        'MovieGenre.Genre.name'
    ),
    'recursive' => 2,
    'limit' => 10
);
$this->paginate = $options;
$this->set('movies',$this->paginate());

真正的问题从这里开始,我得到了所有的电影,即使它与类型“戏剧”无关。
我哪里错了?

让我解释一下数据库表:

表:电影
 ----------------------------
 | id | title | description |
 ----------------------------
 | 1  | mov1  | something1  |
 | 2  | mov2  | something2  |
 | 3  | mov3  | something3  |
 ----------------------------

表:流派
 ---------------
 | id | name   |
 ---------------
 | 1  | drama  |
 | 2  | sci-fi |
 | 3  | comedy |
 ---------------

表:movie_genres
 -------------------------------
 | id | movie_id | genre_id    |
 -------------------------------
 | 1  | 1        | 1           |
 | 2  | 1        | 2           |
 | 3  | 2        | 2           |
 -------------------------------

在这里你可以看到一个movie_id有多个genre_id。我应该只得到 mov1 但我把两部电影都放在一个数组中。

~~ 编辑 ~~
哎呀!
抱歉忘了提及,我在 MoviesController 中使用此代码。所有 3 个表都有各自的 Controller 。所以请建议我可以使用哪个 Controller 。

编辑:2
class Movie extends AppModel {
    public $displayField = 'title';

    public $actsAs = array('Containable');

    public $hasMany = array(
        'MovieGenre' => array(
            'className' => 'MovieGenre',
            'foreignKey' => 'movie_id',
            'dependent' => false,
            'conditions' => '',
            'fields' => '',
            'order' => '',
            'limit' => '',
            'offset' => '',
            'exclusive' => '',
            'finderQuery' => '',
            'counterQuery' => ''
        ),
        'MovieLanguage' => array(
            'className' => 'MovieLanguage',
            'foreignKey' => 'movie_id',
            'dependent' => false,
            'conditions' => '',
            'fields' => '',
            'order' => '',
            'limit' => '',
            'offset' => '',
            'exclusive' => '',
            'finderQuery' => '',
            'counterQuery' => ''
        ),
    );

}

型号: 流派
class Genre extends AppModel {

    public $displayField = 'name';

    public $hasAndBelongsToMany = array(
        'Movie' => array(
            'className' => 'Movie',
            'joinTable' => 'movie_genres',
            'foreignKey' => 'genre_id',
            'associationForeignKey' => 'movie_id',
            'unique' => 'keepExisting',
            'conditions' => '',
            'fields' => '',
            'order' => '',
            'limit' => '',
            'offset' => '',
            'finderQuery' => '',
            'deleteQuery' => '',
            'insertQuery' => ''
        )
    );

}

型号:电影类型
class MovieGenre extends AppModel {

    public $belongsTo = array(
        'Movie' => array(
            'className' => 'Movie',
            'foreignKey' => 'movie_id',
            'conditions' => '',
            'fields' => '',
            'order' => ''
        ),
        'Genre' => array(
            'className' => 'Genre',
            'foreignKey' => 'genre_id',
            'conditions' => '',
            'fields' => '',
            'order' => ''
        )
    );
}

最佳答案

TLDR: 在 Genre 上查找并包含它的 Movies,或使用 joins() - 在 Movies 上进行搜索并包含带有条件的 Genre 对您想要的结果不起作用。

解释:

下面是您更正的“包含”代码,但更重要的是,对“流派”执行“包含”不会返回您正在寻找的结果。

它的作用 - 根据您的条件限制包含的流派......因此它将拉取所有电影,并包含与 $genre 匹配的流派。

解决方案(取决于您的需求):

解决方案 1)

  • 在 Genre 上做一个 find(),有条件,并包含它的电影。这将拉动匹配的流派,然后拉相关的电影。

  • 解决方案 2) - 我推荐的那个
  • 使用“joins()”:

  • $conditions = array();
    $conditions['joins'] = array(
        array(
            'table' => 'genres_movies', //or movie_genres if you've specified it as the table to use
            'alias' => 'GenresMovie',
            'type' => 'INNER'
            'conditions' => array(
                'GenresMovie.movie_id = Movie.id'
            )
        ),
        array(
            'table' => 'genres',
            'alias' => 'Genre',
            'type' => 'INNER',
            'conditions' => array(
                'Genre.id = GenresMovie.genre_id',
                'Genre.name = "' . $genre . '"'
            )
        )
    );
    $this->Movie->find('all', $conditions);
    

    您编辑的(更正的 imo)“包含”示例
    //edited example
    $genre = "drama";
    
    $options = array(
        'contain' => array(
            'Genre' => array(
                'conditions' => array('Genre.name' => $genre)
            )
        ),
        'recursive' => -1,
        'limit' => 10
    );
    $this->paginate = $options;
    $this->set('movies', $this->paginate('Movie'));
    
  • 你没有“包含”你正在查找的模型(即我从你的包含数组中删除了“电影”)。
  • 你只包含模型,而不是像“MovieGenre.Genre”这样的东西(我想不出任何时候你会使用 '.' 连接模型)
  • 递归必须为-1才能使用Containable-您应该在AppModel中将其设置为-1并忘记递归的概念-
  • 不好

    关于cakephp - 在 CakePHP 中为 Containable 添加条件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12842683/

    10-12 15:05