Как настроить модель Yii для реляционных запросов? - PullRequest
1 голос
/ 20 сентября 2011

Немного новичок в yii, и у меня возникли проблемы при попытке выполнить запрос соединения в моей модели, сгенерированной gii.

Резюме:
Я хочу вернуть видео (таблица "видео"), которые соответствуют определенным критериям поиска. Для этого у меня есть таблица 'videos', а у меня есть другая таблица 'searchmaps'. Все поисковые карты привязывают video_id к search_id, чтобы я мог отслеживать несколько видео, соответствующих критериям для одного сценария поиска.

Что я пробовал:
Я попытался следовать yii документам для реляционных запросов , но я предполагаю, что мне что-то еще не хватает ... Ниже мой код. Что я делаю не так ??

( Примечание. Я хочу вернуть модель с использованием CActiveDataProvider )

Таблицы:

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 ;

Классы:

Вот класс Controller:

//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,
        ));
}

Ниже приведен основной класс модели:

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

Вот класс модели связанной таблицы

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

1 Ответ

3 голосов
/ 20 сентября 2011

Во-первых, я бы предложил использовать таблицы InnoDB, чтобы вы могли установить правильные внешние ключи - если вы сделаете это, gii сгенерирует для вас основные отношения.Если вы можете конвертировать ваши таблицы, то вы можете добавить fk с помощью:

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

Ваши отношения выглядят не совсем правильно, кажется, они должны быть:

в модели Видео:

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

в модели поисковых карт:

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

, тогда ваш dataProvider может выглядеть примерно так:

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

, чтобы попробовать его, вы можете вывести простую сетку в вашем представлениис чем-то вроде:

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

Опять же, я бы настоятельно рекомендовал использовать внешние ключи в вашей таблице и просматривать выходные данные отношений gii, и как только вы поймете, что он делает, его будет намного проще настроить.Кроме того, использование внешних ключей обеспечит поддержание отношений.Вы можете использовать такой инструмент, как MysqlWorkbench или аналогичный, если вам нужна помощь в создании внешних ключей.

...