以前我依赖递归,但我没有得到一些解决方案,然后我发现 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 张 table 都有各自的 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:在类型上进行查找并包含其电影,或者使用 joins() - 在电影上进行搜索并包含带条件的类型将无法获得您想要的结果。
<小时/>说明:
下面是更正后的“包含”代码,但更重要的是,对流派执行“包含”不会返回您要查找的结果。
它的作用 - 根据您的情况限制包含的类型...因此它将提取所有电影,并包含与 $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);
<小时/>
您编辑的(在我看来更正的)“包含”示例
//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/