在CakePHP中添加条件为可容纳 [英] Adding conditions to Containable in CakePHP

查看:137
本文介绍了在CakePHP中添加条件为可容纳的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以前我是依靠递归,但我没有得到解决方案的一些,然后我发现Containable工程正常为这些。



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



我有以下代码:

  // example 
$ genre =drama;

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

真正的问题从这里开始,我得到所有的电影,即使它不与类型戏剧。
我在哪里出错?



让我解释数据库表:



  -------------------------- -  
| id |标题|描述|
----------------------------
| 1 | mov1 | something1 |
| 2 | mov2 | something2 |
| 3 | mov3 | something3 |
----------------------------

表:genres

  ------------ --- 
| id |名称|
---------------
| 1 |戏剧|
| 2 |科幻|
| 3 |喜剧|
---------------

表: movie_genres

  ------------------------- ------ 
| id | movie_id | genre_id |
-------------------------------
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 2 |
-------------------------------

在这里你可以看到一个movie_id有多个genre_id。我应该只得到 mov1 ,但我得到两个电影的数组。



~~ ~~
oops!
抱歉忘了提及,我在 MoviesController 中使用这个代码。所有3表有各自的控制器。



编辑:2 p $ p> 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'=& ,
'foreignKey'=>'movie_id',
'dependent'=> false,
'conditions'=>'',
'fields'=& '',
'order'=>'',
'limit'=>'',
'offset'=>'',
'exclusive' >'',
'finderQuery'=>'',
'counterQuery'=> ''
),
);

}

型号:Genre


b $ b

  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'=>'' $ b'offset'=>'',
'finderQuery'=>'',
'deleteQuery'=>'',
'insertQuery'=& b $ b)
);

}

型号:MovieGenre


b $ b

  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: / strong>在Genre上找到并包含它的Movies,或使用joins() - 在Movies上搜索并包含具有条件的Genre将不会对您想要的结果起作用。






说明:



下面是您修正的包含代码,重要的是,对类型执行包含不会返回您要查找的结果。



功能 - 根据您的条件限制包含的类型。 。因此它将拉取所有电影,并包含匹配 $ genre 的类型。






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




  • 在类型上执行 find(),包含条件,并包含电影。



解决方案2)




  • 使用'joins()':






  $ conditions = array(); 
$ conditions ['joins'] = array(
array(
'table'=>'genres_movies',//或movie_genres如果您将它指定为使用
'alias'=>'GenresMovie',
'type'=>'INNER'
'conditions'=> array(
'GenresMovie.movi​​e_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);






contains'example

  //编辑示例
$ genre =drama;

$ options = array(
'contains'=> array(
'Genre'=> array(
'conditions'=& genre.name'=> $ genre)

),
'recursive'=> -1,
'limit'=> 10
) ;
$ this-> paginate = $ options;
$ this-> set('movies',$ this-> paginate('Movie'));




  1. 您不会包含发现on(即我从你的包含数组中删除'Movie')。

  2. 你只包含模型,而不是像MovieGenre.Genre(我不能想到任何时候,你会使用'。'连接模型)

  3. 递归需要为-1才能使用Containable - 应在AppModel中将其设置为-1,并忽略递归的概念 - >


Previously I was relying on recursive, but I didn't get solution for some, then I found that Containable works fine for these.

I am developing a movie review website. In that I need to show the list of movies which is related to a particular Genre.

I have this below code:

//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());

The real problem starts here, I get all the movies, even if its not related to the genre "drama". Where am I going wrong ?

Let me explain the database table:

Table: movies

 ----------------------------
 | id | title | description |
 ----------------------------
 | 1  | mov1  | something1  |
 | 2  | mov2  | something2  |
 | 3  | mov3  | something3  |
 ----------------------------

Table: genres

 ---------------
 | id | name   |
 ---------------
 | 1  | drama  |
 | 2  | sci-fi |
 | 3  | comedy |
 ---------------

Table: movie_genres

 -------------------------------
 | id | movie_id | genre_id    |
 -------------------------------
 | 1  | 1        | 1           |
 | 2  | 1        | 2           |
 | 3  | 2        | 2           |
 -------------------------------

Here you can see that one movie_id has multiple genre_id. I should get only mov1 but I'm getting both movies in an array.

~~ EDIT ~~ oops!! sorry forgot to mention, I'm using this code in MoviesController. All 3 table has respective controller. So pls suggest me in which controller I can use.

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

}

Model: Genre

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

}

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

解决方案

TLDR: do your find on Genre and contain it's Movies, or use joins() - doing your search on Movies and containing Genre with conditions won't work for the results you want.


Explanation:

Below is your corrected 'contain' code, but more importantly, doing a 'contain' on Genre won't return the results you're looking for.

What it does - limits the contained genres based on your condition... so it will pull ALL movies, and contain the genres that match $genre.


Solutions (depending on your needs):

Solution 1)

  • Do a find() on Genre, with the condition, and contain it's movies. This will pull the genre that matches, then only the movies that are related to it.

Solution 2) - the one I'd recommend

  • Use '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);


Your edited (corrected imo) 'contain' example

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

  1. you don't "contain" the model you're doing the find on (ie I removed 'Movie' from your contain array).
  2. you only contain models, not things like "MovieGenre.Genre" (I can't think of any time you would use '.' concatenated models)
  3. recursive needs to be -1 to use Containable - you should set this to -1 in the AppModel and forget the concept of recursive - it's bad

这篇关于在CakePHP中添加条件为可容纳的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆