Exebeche
@Exebeche
Осваиваю программирование

Почему фильтр товаров работает по разному на фронт и на бекенд?

Долгими мучениями получилось сделать фильтр для товаров на сайте.
При выборе родительской категории выводится товар из родительской и дочерних категорий.
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;
    }


На бекенде все чудесно работает. Создается массив типа:
array (size=2)
  0 => string '5' (length=1)
  1 => string '3' (length=1)

Где 3 это родитель, а 5 - дочерняя категории

Вроде все хорошо и можно радоваться, но на фронтенде, оказалось, создается массив типа:
array (size=1)
  0 => 
    array (size=1)
      0 => string '3' (length=1)

И при этом потомок куда-то исчезает без каких либо видимых причин. (Может семья неблагополучная?).

Фильтр один и тот-же, но вот такая оказия.

Выводится на фронт в контроллере:
public function actionNew()
    {
        $searchModel = new ProductSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
        return $this->render('new', [
            'dataProvider' => $dataProvider,
            'searchModel' => $searchModel,
        ]);
    }


Вьюха:
<?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(); ?>


На фронте при фильтрации формируется урл с лишними знаками "[]",
?ProductSearch[category_id]=&ProductSearch[category_id][]=3&ProductSearch[designer_id]=

если ручками их убрать, то результат получается правильный и массив строится как положено.

Как это победить и куда копать, а то уже, кажется все перепробовал?
  • Вопрос задан
  • 101 просмотр
Пригласить эксперта
Ответы на вопрос 1
ap0stal
@ap0stal
Web-разработчик
Практически всё, что можно было сделать неправильно, вы сделали неправильно.

1. В ProductSearch введите свойство $type и избавьтесь от ужасного if (Yii::$app->controller->route == 'shop/new')
2. Уберите ненужные поля фильтрации, типа
->andFilterWhere(['like', 'meta_key', $this->meta_key])

3. $this->registerJs предполагает, что ваш код обернется в
$("document").ready(function() {
..
});
а вы этот блок засовываете в $this->registerJs();
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы