2011-09-20 6 views
1

Un peu nouveau sur yii et j'ai eu du mal à essayer de faire une requête de jointure dans mon modèle généré par gii.Comment configurer mon modèle Yii pour les requêtes relationnelles?

Résumé:
Je veux retourner les vidéos (table « vidéos ») qui satisfont à des critères de recherche spécifiques. Pour ce faire, j'ai ma table 'vidéos', et j'ai une autre table 'searchmaps'. Tous searchmaps ne s'associer un video_id à un search_id afin que je puisse garder une trace de plusieurs vidéos répondant aux critères d'un scénario de recherche unique ..

Ce que j'ai essayé:
I Tried suivante yii docs for relational queries mais je suppose que Il me manque encore quelque chose ... Voici mon code. Qu'est-ce que je fais mal??

(Note: Je voudrais revenir un modèle en utilisant CActiveDataProvider)

Tables:

CREATE TABLE IF NOT EXISTS `videos` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `user_id` int(11) NOT NULL, 
    `directory` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `created` varchar(20) COLLATE utf8_unicode_ci NOT NULL, 
    `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `description` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `category` int(2) NOT NULL, 
    `tags` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `filename` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `filetype` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `duration` int(11) NOT NULL, 
    `status` int(1) NOT NULL, 
    `error` text COLLATE utf8_unicode_ci NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=17 ; 


CREATE TABLE IF NOT EXISTS `searchmaps` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `search_id` int(11) NOT NULL, 
    `video_id` int(11) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=69 ; 

Classes:

Voici la classe contrôleur:

//From VideosController.php 

... 

public function actionIndex($searchmap_id) 
{ 
    $dataProvider = new CActiveDataProvider('SearchVideos', array(
      'criteria' => array(
     'with' => array('search.video_id','search.search_id'), 
     'together' => true, 
      'condition'=>'videos.id = search.video_id AND search.search_id='.$searchmap_id, 
       ))); 
     $this->render('index',array(
     'dataProvider'=>$dataProvider, 
     )); 
} 

Ci-dessous est la principale classe de modèle:

// From Videos.php 

... 

/** 
* @return array relational rules. 
*/ 

public function relations() 
{ 
    // NOTE: you may need to adjust the relation name and the related 
    // class name for the relations automatically generated below. 
    return array(
    'search'=>array(self::BELONGS_TO, 'Searchmaps', 'video_id'), 
      ); 
} 

Voici la classe modèle de la table liée

// From Searchmaps.php 

    ... 

/** 
* @return array relational rules. 
*/ 

public function relations() 
{ 
    // Each row has a search_id and a video_id relating to a specific video 
    // Multiple rows may have different videos but share the same search_id 
    return array(
    'video'=>array(self::HAS_ONE, 'Videos', 'video_id'), 
    ); 
} 

Répondre

3

D'abord, je suggère d'utiliser les tables InnoDB afin que vous pouvez configurer l'étranger approprié clés - si vous faites cela, alors gii générera les relations de base pour vous. Si vous pouvez convertir vos tables, vous pouvez ajouter le fk:

ALTER TABLE `searchmaps` 
ADD CONSTRAINT `searchmaps_ibfk_1` FOREIGN KEY (`video_id`) REFERENCES `videos` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE; 

Vos relations ne regardent pas tout à fait raison, semble comme ils devraient être:

dans le modèle Vidéos:

return array(
    'searchmaps' => array(self::HAS_MANY, 'Searchmaps', 'video_id'), 
); 

dans le modèle Searchmaps:

return array(
    'video' => array(self::BELONGS_TO, 'Videos', 'video_id'), 
); 

alors votre fournisseur de données peut ressembler à:

$dataProvider=new CActiveDataProvider('Videos',array(
    'criteria'=>array(
     'with'=>'searchmaps', 
     'together' => true, 
     'condition' => 'searchmaps.search_id='.$search_id, 
    ) 
)); 

pour l'essayer vous pouvez produire une simple grille dans votre vue avec quelque chose comme:

$this->widget('zii.widgets.grid.CGridView', array(
    'id'=>'videos-grid', 
    'dataProvider'=>$dataProvider 
)); 

Encore une fois, je recommande fortement d'utiliser les clés étrangères dans votre table et afficher les sorties GII des relations et une fois vous comprenez ce qu'il fait, il sera beaucoup plus facile de le personnaliser. En outre, l'utilisation de clés étrangères assurera le maintien des relations. Vous pouvez utiliser un outil comme MysqlWorkbench ou similaire si vous avez besoin d'aide pour créer les clés étrangères.

+1

Bonne réponse. Je vais essayer votre solution cet après-midi. – m0rtimer

Questions connexes