Как в GridView\ListView получить посты из дочерних категорий?

Обсуждение документации второй версии фреймворка. Переводы Cookbook и авторские рецепты.
Ответить
kololobo
Сообщения: 9
Зарегистрирован: 2016.07.18, 11:04

Как в GridView\ListView получить посты из дочерних категорий?

Сообщение kololobo »

Имеется сайт с категориями и постами.
Категории могут быть очерними и родительскими по parent_id.
Все прекрасно работает, за исключением одного момента с фильтрацией - при выборе в фильтре родительской категории нужно выводить посты из дочерних категорий.
Долго мучился, но так и ниасилил.

Создал связь виатабле и вардампом все красиво, но...

Модель 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

Код: Выделить всё


    /**
     * @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

Код: Выделить всё

    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

Код: Выделить всё

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

        // 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;
    }
Как видно из кода - пытался изо всех сил пристроить childrenPosts, но все без успешно.
Пожалуйста, подскажите, что я где не так и объясните, пожалуйста, как нужно сделать чтобы было правильно.

З.Ы.
Желательно своими словами т.к.прочитанное и просмотренное ранее не принесло результата :(
kololobo
Сообщения: 9
Зарегистрирован: 2016.07.18, 11:04

Re: Как в GridView\ListView получить посты из дочерних категорий?

Сообщение kololobo »

Спасибо.
Буду вникать
kololobo
Сообщения: 9
Зарегистрирован: 2016.07.18, 11:04

Re: Как в GridView\ListView получить посты из дочерних категорий?

Сообщение kololobo »

Ниасилил...((
Можно немного подробнее объяснить?

Собирается массив ID-шников дочерних групп, а в фильтр его как втулить-то?
Что-то совсем не догоняю это место.

Перепробовал все до чего додуматься смог. На английском stackowerflow нашел еще 2 варианта - не выводятся у меня в фильтре продукты из дочерних категорий и все...
Аватара пользователя
ElisDN
Сообщения: 5841
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Как в GridView\ListView получить посты из дочерних категорий?

Сообщение ElisDN »

Код: Выделить всё

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)]);
}
kololobo
Сообщения: 9
Зарегистрирован: 2016.07.18, 11:04

Re: Как в GridView\ListView получить посты из дочерних категорий?

Сообщение kololobo »

Я создал ProductQuery как в приведенной вами ссылке...
Просмотрел на предмет различий другие модели, пробовал пристроить этот кусок кода к другим местам, но фильтр все равно не срабатывает при выборе родительской категории...
Только вардампами получается список продуктов вывести. чего. только я не писал в модели и фильтры. (((
Сейчас, конечно, еще попробую, но это очень странно...
kololobo
Сообщения: 9
Зарегистрирован: 2016.07.18, 11:04

Re: Как в GridView\ListView получить посты из дочерних категорий?

Сообщение kololobo »

А для чего проверка по category_id? Ведь у всех продуктов этот параметр не пустой...
kololobo
Сообщения: 9
Зарегистрирован: 2016.07.18, 11:04

Re: Как в GridView\ListView получить посты из дочерних категорий?

Сообщение kololobo »

Не туда, оказывается, код вставлял...
Но, теперь, на бекенде все работает как надо, а на фронте в url вставляются знаки "[]" и ессно фильтр не срабатывает...
Пока, получилось, только дочерние выводить..
Что-то клиентской части массивы не нравятся (((
Ответить