查询中的Yii2数据过滤

时间:2016-06-14 17:59:58

标签: php mysql yii2 filtering

在我的Yii2项目中,我将posts表链接到categories表作为多对多关系(posts_categories表)。 在我的Post模型中,我有getByCategory($category_id)函数,它返回该类别的所有帖子。在控制器中我有actionCategory我使用此功能并传递特定类别的所有帖子。我在视图中也有一个GET表单,用于通过GET参数过滤我的帖子(我需要将此值包含在显示的帖子的标题或内容中)。问题是我不知道如何以智能方式在控制器中对我的getByCategory调用应用一些过滤函数。 我的功能代码:

public static function getPostsByCategory($category_id = null)
{
    $posts = Post::find()
        ->select('posts.*')
        ->innerJoin('posts_categories', '`posts`.`id` = `posts_categories`.`post_id`')
        ->where(['posts_categories.category_id' => $category_id])
        ->orderBy(['date_create' => SORT_DESC])
        ->all();
    return $posts;
}

控制器操作:

public function actionCategory($id)
{
    $posts = Post::getPostsByCategory($id);
    return $this->render('index', array('all_posts' => $posts));
}

我的所有想法,例如使用“如果$ _GET不为空 - 在控制器或模型中使用一个查询 - 如果为空 - 另一个查询”这样的语句看起来很麻烦并导致在我还需要的其他操作中复制代码我的$ _GET过滤。你能建议吗?感谢。

1 个答案:

答案 0 :(得分:2)

请使用ActiveQuery来处理数据库查询。它简单而有效。

简单来说,创建Class

class PostQuery extends \yii\db\ActiveQuery
{
    public function byCategory($id){
        $junction_table = '{{%posts_categories}}';
        $this
            ->innerJoin($junction_table, Post::tableName()'.id='.$junction_table.'.post_id')
            ->where([$junction_table.'.category_id' => $id]);
    }

    public function orderByDateCreated($sort_type = SORT_DESC){
        return $this
            ->orderBy(['date_create' => $sort_type]);
    }

    /**
     * @inheritdoc
     * @return Post[]|array
     */
    public function all($db = null)
    {
        return parent::all($db);
    }

    /**
     * @inheritdoc
     * @return Post|array|null
     */
    public function one($db = null)
    {
        return parent::one($db);
    }
}

find方法添加到Post模型:

public static function find()
{
    return new PostQuery(get_called_class());
}

对于搜索和过滤器,使用从PostSearch模型扩展的Post模型。

class PostSearch extends Post
{
    public $category_id;

    public function rules(){
        return [
            ['category_id', 'integer']
        ];
    }

    public function search($params = []){

        $query = Post::find();

        $query
            ->orderByDateCreated();

        $dataProvider = new ActiveDataProvider([
            'query' => $query
        ]);

        if( !($this->load($params) && $this->validate()) ){
            return $dataProvider;
        }

        if($this->category_id)
            $query->byCategory($this->category_id)

        return $dataProvider;
    }
}

在带搜索功能的控制器中

public function actionIndex(){
    $searchModel = new ArticleSearch();

    $dataProvider = $searchModel->search(\Yii::$app->request->post()); //data from filter form

    return $this->render('index', compact('dataProvider'));
}

没有ActiveDataProvider

public function actionIndex(){
    $searchModel = new ArticleSearch();

    $query = Post::find();

    $query
        ->orderByDateCreated();

    if($searchModel->load(\Yii::$app->request->post()) && $searchModel->validate()){
        if($this->category_id)
            $query->byCategory($this->category_id)
    }

    $posts = $query->all();

    return $this->render('index', compact('posts'));
}