Yii关系搜索


Yii relational search

在询问之前,我试着"做作业",但我尝试的方法似乎都不起作用,所以我需要帮助。(我不是Yii的专家)

我的问题是,我希望在我的索引页面上有一个搜索框,它可以帮助我按标签搜索电影。我发现了一篇有用的文章,所以基本上我就是这样开始的。

我有以下表格:

电影

标签

movie_has_tag(其中包含movie_id和tag_id)

//我想我需要的是movie_title和tag_name

BaseMovie:中的关系

public function relations(){
    return array(
        'tags' => array(self::MANY_MANY, 'Tag', 'movie_has_tag(movie_id, tag_id)'),
    );
}

BaseTag:中的关系

public function relations(){
    return array(
        'movies' => array(self::MANY_MANY, 'Movie', 'movie_has_tag(tag_id, movie_id)'),
    );
}

我是这样尝试的:

public function actionIndex(){
    if( isset($_GET['q']) ){
        $model = new Movie($scenario='search');
        $model->unsetAttributes();
        $tag = $_GET['q'];
        // this is how I tried
        $tags = Movie::model()->with('tags')->findAllByAttributes( array('movie_title' => $tag));
        $this->render('index',array(
            'dataProvider'=>$model->search(),  
        ));
}

使用此代码,当我开始在搜索框中键入时,不会发生任何事情。


编辑:
@Stu

我已经阅读了链接,并提出了以下内容。我将此关系添加到BaseMovie:

'tagz' => array(self::HAS_MANY, 'Tag', array('movie_id'=>'tag_id', 'through'=>'MovieTags')).

然后我编辑了正在操作的东西索引:

if( isset($_GET['q']) ){
        $model = new Movie($scenario='search');
        $model->unsetAttributes();
        $movies = Movie::model()->withTag($_GET['q'])->findAll();
        $tags = $movies->movieTags;
}

当我开始输入即时搜索框时,它就变成了咒语,所有的电影都消失了(即使我删除了输入的内容,它们也不会回来。我必须刷新页面)。

编辑v2:视图非常简单(_V):

<div class="view">
    <?php echo CHtml::encode($data->title); ?>
</div>

其他一切(比如索引页)都和我第一次提到的链接一样。

好的,我已经阅读了你在这里写的内容(问题和第一个答案),并将在你的"EDIT:@Stu"标记之前解决你的问题,因为在那之后你开始做一些我不理解的奇怪事情。

您有两个型号MovieTagMovie模型中的关系如您之前所写:

public function relations(){
  return array(
    'tags' => array(self::MANY_MANY, 'Tag', 'movie_has_tag(movie_id, tag_id)'),
  );
}

Tag模型中的关系与您之前所写的相同:

public function relations(){
  return array(
    'movies' => array(self::MANY_MANY, 'Movie', 'movie_has_tag(tag_id, movie_id)'),
  );
}

现在您可以在Movie模型中创建新方法:

public function searchByTag($q)
{
    $criteria=new CDbCriteria;
    $criteria->with = 'tags';
    $criteria->together = true;
    $criteria->compare('`tags`.`name`', $q, true, 'OR');
    // You can add here another comparision to search in your movie title, for example
    // $criteria->compare('`t`.`title`', $q, true, 'OR');
    return new CActiveDataProvider($this, array(
        'criteria'=>$criteria,
    ));
}

在你的控制器中,动作应该是这样的:

public function actionIndex() {
    if( isset($_GET['q']) ) {
        $tag = $_GET['q']; // Please add needed safety measures, for example with HTMLPurifier
        $this->render('index', array(
            'dataProvider'=>Movie::model()->searchByTag($tag),  
        ));
    } else
        $this->render('index');
}

希望这是有用的。