在CakePHP中添加条件到Containable

pra*_*mar 6 recursion cakephp conditional-statements containable cakephp-2.0

以前我依靠递归,但我没有得到一些解决方案,然后我发现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());
Run Code Online (Sandbox Code Playgroud)

真正的问题从这里开始,我得到所有的电影,即使它与流派"戏剧"无关.我哪里错了?

让我解释一下数据库表:

表:电影

 ----------------------------
 | id | title | description |
 ----------------------------
 | 1  | mov1  | something1  |
 | 2  | mov2  | something2  |
 | 3  | mov3  | something3  |
 ----------------------------
Run Code Online (Sandbox Code Playgroud)

表:流派

 ---------------
 | id | name   |
 ---------------
 | 1  | drama  |
 | 2  | sci-fi |
 | 3  | comedy |
 ---------------
Run Code Online (Sandbox Code Playgroud)

表:movie_genres

 -------------------------------
 | id | movie_id | genre_id    |
 -------------------------------
 | 1  | 1        | 1           |
 | 2  | 1        | 2           |
 | 3  | 2        | 2           |
 -------------------------------
Run Code Online (Sandbox Code Playgroud)

在这里你可以看到一个movie_id有多个genre_id.我应该只得到,mov1但我得到两个电影阵列.

~~ 编辑 ~~哎呀!抱歉忘了提,我正在使用此代码MoviesController.所有3个表都有各自的控制器.所以请建议我使用哪个控制器.

编辑: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' => ''
        ),
    );

}
Run Code Online (Sandbox Code Playgroud)

型号:类型

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' => ''
        )
    );

}
Run Code Online (Sandbox Code Playgroud)

型号:MovieGenre

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' => ''
        )
    );
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*ave 13

TLDR:你在Genre上找到它并包含它的电影,或者使用连接() - 在电影上搜索并包含条件的类型将不适用于你想要的结果.


说明:

以下是您更正的"包含"代码,但更重要的是,在"流派"上执行"包含"不会返回您要查找的结果.

它的作用 - 根据你的情况限制所包含的类型...所以它将拉动所有电影,并包含匹配的类型$genre.


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

解决方案1)

  • find()在类型上做一个条件,并包含它的电影.这将拉动匹配的类型,然后只播放与其相关的电影.

解决方案2) - 我推荐的那个

  • 使用'join()':

$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);
Run Code Online (Sandbox Code Playgroud)

您编辑的(更正的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'));
Run Code Online (Sandbox Code Playgroud)
  1. 你没有"包含"你正在进行查找的模型(即我从你的包含数组中删除了'电影').
  2. 你只包含模特,而不是像"MovieGenre.Genre"这样的东西(我想不出你会用'.'连接模型的任何时候)
  3. 递归需要-1才能使用Containable - 你应该在AppModel中将它设置为-1并忘记递归的概念 - 这很糟糕