2012-10-11 10 views
6

Wcześniej opierałem się na rekurencji, ale nie otrzymałem rozwiązania dla niektórych, a następnie stwierdziłem, że Containable działa dobrze dla nich.Dodawanie warunków do Containable w CakePHP

Zajmuję się tworzeniem strony z recenzjami filmów. W tym celu muszę pokazać listę filmów związanych z konkretnym gatunkiem.

mam ten kod poniżej:

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

Prawdziwy problem zaczyna się tutaj, mam wszystkie filmy, nawet jeśli jej nie związane z gatunku „dramat”. Gdzie się mylę?

Pozwól mi wyjaśnić tabeli bazy danych:

tabeli: filmów

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

Tabela: genres

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

Tabela: movie_genres

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

Tutaj można zobaczyć, że jeden mov ie_id ma wiele identyfikatorów gatunkowych. Powinienem dostać tylko mov1, ale dostaję oba filmy w tablicy.

~~ EDYTOWANIE ~~ oops !! Przepraszam, zapomniałem wspomnieć, używam tego kodu w MoviesController. Wszystkie 3 tabele mają odpowiedni kontroler. Więc pls sugerują mi, w którym kontroler mogę korzystać.

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: Gatunek

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

Gdzie jest twój model? –

+0

Dodałem model :) –

Odpowiedz

13

TLDR: zrobić swoje znalezisko na gatunek i zawierają to filmy, lub użyj join() - robiąc ci r wyszukiwanie filmów i zawierające gatunek z warunkami nie będzie działać dla pożądanych rezultatów.


Objaśnienie:

Poniżej poprawiony „zawierać” kod, ale co ważniejsze, robi „zawierać” na gatunek nie zwróci wyników, których szukasz.

Co robi - ogranicza zawarte w nim gatunki w oparciu o twój stan ... tak, że przyciągnie WSZYSTKIE filmy i zawiera gatunki pasujące do $genre.


Solutions (zależnie od potrzeb):

Rozwiązanie 1)

  • zrobić find() na gatunku, pod warunkiem, i zawierać jego filmy. Spowoduje to przyciągnięcie pasującego gatunku, a następnie tylko powiązanych z nim filmów.

Rozwiązanie 2) - jeden ja polecam

  • użycia 'dołącza()':

$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); 

edytowane (corrected imo) "zawierają" exampl e

//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. nie „zawierać” model Robisz znaleźć na (czyli usunąłem „film” z zawierać tablicy).
  2. zawierają tylko modele, a nie takie rzeczy, jak "MovieGenre.Genre" (nie mogę myśleć o używaniu modeli ".").
  3. Rekursywność musi wynosić -1, aby używać Containable - powinieneś ustawić to do -1 w AppModelu i zapomnij o koncepcji rekursywnej - to jest złe
+0

Awesome bro, The joins working perfectly. Czy możesz zaproponować jakąś zaawansowaną książkę dla cakephpa? Nie mogłem takiej książki. 'Thanks A Lot:)' działa idealnie, tęsknisz za niektórymi '' 'quotes: P –

+1

http://book.cakephp.org/2.0 jest niesamowity i użyłem tego. – Dave

+1

Bardzo się cieszę, że pomogło/zadziałało. Naprawiono cytaty (wygląda na to, że próbowałeś zbyt). – Dave