A
A
Alexander Stepanov2018-02-08 14:09:28
Yii
Alexander Stepanov, 2018-02-08 14:09:28

How to display posts from child categories in Yii2 gridView/listView filter?

There is a site with categories and posts. Categories can be child and parent by parent_id. Everything works fine, except for one thing with filtering - when you select a parent category in the filter, you need to display posts from child categories. He suffered for a long time, but niasilil.
Created a viatable connection and wardump everything is beautifully displayed from the model, but when choosing a parent in grid / listView, I get empty-empty
Model Category

/**
 * @return \yii\db\ActiveQuery
 */
public function getParent()
{
    return $this->hasOne(Category::className(), ['id' => 'parent_id']);
}

/**
 * @return \yii\db\ActiveQuery
 */
public function getCategories()
{
    return $this->hasMany(Category::className(), ['parent_id' => 'id'])->with('posts');
}

/**
 * @return \yii\db\ActiveQuery
 */
public function getPost()
{
    return $this->hasMany(Post::className(), ['category_id' => 'id']);
}

public function getChildrenPosts()
{
    return $this->hasMany(Post::className(), ['category_id' => 'id'])->indexBy('id')->asArray()->viaTable('{{%category}}', ['parent_id' =>'id']);
}

Post model
/**
 * @return \yii\db\ActiveQuery
 */
public function getCategory()
{
    return $this->hasOne(Category::className(), ['id' => 'category_id']);
}

public function getChildrenPosts()
{
    return $this->hasMany(Post::className(), ['category_id' => 'id'])->indexBy('id')->asArray()->viaTable('{{%category}}', ['parent_id' =>'id']);
}

PostSearch Model
public function search($params)
{
    $query = Post::find()->with(['category', 'childrenPosts']);

    // add conditions that should always apply here

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

    $this->load($params);

    if (!$this->validate()) {
        // uncomment the following line if you do not want to return any records when validation fails
        // $query->where('0=1');
        return $dataProvider;
    }

    // grid filtering conditions
    $query->andFilterWhere([
        'id' => $this->id,
        'category_id' => $this->category_id,
        'content' => $this->content,
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ]);

    return $dataProvider;
}

CategorySearch Model
public function search($params)
{
    $query = Category::find()
        ->select(['{{%category}}.*', 'posts_count' => new Expression('COUNT({{%post}}.id)')])
        ->joinWith(['post'], false)
        ->groupBy('{{%category}}.id')
        ->with(['parent', 'childrenPosts']);

    // add conditions that should always apply here

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

    $this->load($params);

    if (!$this->validate()) {
        // uncomment the following line if you do not want to return any records when validation fails
        // $query->where('0=1');
        return $dataProvider;
    }

    // grid filtering conditions
    $query->andFilterWhere([
        'id' => $this->id,
        'parent_id' => $this->parent_id,
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ]);

    return $dataProvider;
}

As you can see from the code - I tried my best to attach childrenPosts, but all without success. Please tell me what I'm doing wrong and please explain how to do it right.
Z.Y. Preferably in your own words, because what I read and viewed earlier did not bring results :( I received a response from Dmitry Eliseev:
if (!empty($this->category_id)) {
$ids = [$this->category_id];
$childrenIds = $ids;
while ($childrenIds = Category::find()->select('id')->andWhere(['parent_id' => $childrenIds])->column()) {
    $ids = array_merge($ids, $childrenIds);
}
$query->andWhere(['category_id' => array_unique($ids)]);
}

But no matter how I tried to insert it, to modernize no result.
It really needs to be sorted out

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Alexander Stepanov, 2018-02-10
@Exebeche

Helped solve on workzilla

public function search($params)
    {
        $query = Product::find()
            ->from(['p' => Product::tableName()])
            ->with(['designer', 'category']);

        // add conditions that should always apply here

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

        $this->load($params);

        if (!$this->validate()) {
            // uncomment the following line if you do not want to return any records when validation fails
            // $query->where('0=1');
            return $dataProvider;
        }

        // grid filtering conditions
        $query->andFilterWhere([
            'p.id' => $this->id,
            //'p.category_id' => $this->category_id,
            'p.designer_id' => $this->designer_id,
            'p.price' => $this->price,
            'p.new' => $this->new,
            'p.hit' => $this->hit,
            'p.sale' => $this->sale,
            'p.created_at' => $this->created_at,
            'p.updated_at' => $this->updated_at,
//            'p2.childrenProducts' => $this->category_id
        ]);

        if (!empty($this->category_id)) {
            $ids = Category::find()->andWhere(['parent_id'=>[$this->category_id]])->alias('p2')->column();
            $ids[] = $this->category_id;
            $query->andWhere(['p.category_id' => array_unique($ids)]);
    }

        $query->andFilterWhere(['like', 'title', $this->title])
            ->andFilterWhere(['like', 'art', $this->art])
            ->andFilterWhere(['like', 'meta_key', $this->meta_key])
            ->andFilterWhere(['like', 'meta_description', $this->meta_description])
            ->andFilterWhere(['like', 'description', $this->description])
            ->andFilterWhere(['like', 'image_alt', $this->image_alt]);

        return $dataProvider;
    }

M
Maxim Timofeev, 2018-02-08
@webinar

Instead ,
apparently it is necessary
. Since you do not need eager loading of individual requests, but join

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question