A
A
Alexander Stepanov2018-02-11 15:25:46
Yii
Alexander Stepanov, 2018-02-11 15:25:46

Why does the product filter work differently on the front and on the backend?

It took a long time to make a filter for the products on the site.
When choosing a parent category, the product from the parent and child categories is displayed.

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.category_id' => $this->category_id
        ]);

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

        if (Yii::$app->controller->route == 'shop/new') {
            $query->andWhere(['new' => 1]);
        }

        if (Yii::$app->controller->route == 'shop/hit') {
            $query->andWhere(['hit' => 1]);
        }

        if (Yii::$app->controller->route == 'shop/sale') {
            $query->andWhere(['sale' => 1]);
        }

        $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;
    }

Everything works great on the back end. An array is created like this:
array (size=2)
  0 => string '5' (length=1)
  1 => string '3' (length=1)

Where 3 is the parent, and 5 is the child category
Everything seems to be fine and you can be happy, but on the frontend, it turned out that an array like this is created:
array (size=1)
  0 => 
    array (size=1)
      0 => string '3' (length=1)

And at the same time, the descendant disappears somewhere for no apparent reason. (Maybe the family is dysfunctional?).
The filter is the same, but here is such an opportunity.
Printed to the front in the controller:
public function actionNew()
    {
        $searchModel = new ProductSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
        return $this->render('new', [
            'dataProvider' => $dataProvider,
            'searchModel' => $searchModel,
        ]);
    }

View:
<?php
$this->registerJs(
    '$("document").ready(function(){
        $(document).on("change", "label", function(e) {
        e.preventDefault();
            $("#filter-form").submit();
        });
    });'
);
?>
<?php Pjax::begin([
    'id' => 'productList',
//    'enablePushState' => false,
//    'enableReplaceState' => false,
]); ?>

    <?php $form = ActiveForm::begin([
        'id' => 'filter-form',
        'action' => ['new'],
        'method' => 'get',
        'options' => ['data-pjax' => true],
    ]); ?>

    <?= $form->field($searchModel, 'category_id')->checkboxList(Category::find()->select(['title', 'id'])->indexBy('id')->column()) ?>

    <?= $form->field($searchModel, 'designer_id')->checkboxList(Designer::find()->where(['status' => 1])->select(['brand_name', 'id'])->indexBy('id')->column()) ?>
    
    <?php ActiveForm::end(); ?>
    <?= ListView::widget([
        'dataProvider' => $dataProvider,
        'itemView' => '_view',
        'itemOptions' => ['class' => 'item'],
        'viewParams' => ['testParam' => 'designer.brand_name'],
        'layout' => "{items}\n{pager}",
        'pager' => [
            'class' => ScrollPager::className(),
            'triggerTemplate' => '<div class="ias-trigger" style="cursor: pointer;"><a>{text}</a></div>',
            'noneLeftText' => 'You reached the end',
            'noneLeftTemplate' => '<div class="ias-noneLeft"><p>{text}</p></div>'
        ]
    ]); ?>

<?php Pjax::end(); ?>

At the front, when filtering, a url with extra signs "[]" is formed,
?ProductSearch[category_id]=&ProductSearch[category_id][]=3&ProductSearch[designer_id]=

if you remove them with handles, then the result is correct and the array is built as expected.
How to win it and where to dig, otherwise it seems that you have tried everything?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Alexander Smirnov, 2018-02-11
@ap0stal

Almost everything that could be done wrong, you did wrong.
1. In ProductSearch, enter a property $typeand get rid of the terrible 2. Remove unnecessary filter fields, such asif (Yii::$app->controller->route == 'shop/new')
3. $this->registerJsassumes that your code will turn into

$("document").ready(function() {
..
});
and you put this block in$this->registerJs();

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question