GridView 中相关模型的过滤器设置

2021-12-24 00:00:00 php yii2 yii gridview

我正在尝试在 Yii2 的 GridView 中设置相关模型的过滤器 小部件,但我不断收到错误,例如过滤器值必须是整数.

我已经关注了这个问题.现在,我有两个模型 Services.phpServiceCharge.php.

ServiceCharge.php 中的关系设置如下:

公共函数getServiceName(){返回 $this->hasOne(Services::className(),['id'=>'service_name']);}

ServiceChargeSearch.php中的代码是这样的:

$查询,]);$dataProvider->sort->attributes['serviceName.services'] = ['asc' =>['serviceName.services' =>SORT_ASC],'desc' =>['serviceName.services' =>SORT_DESC],];$query->joinWith(['serviceName']);$this->load($params);如果 (!$this->validate()) {//如果验证失败时不想记录任何记录,请取消注释以下行//$query->where('0=1');返回 $dataProvider;}$query->andFilterWhere(['id' =>$this->id,//'service_name' =>$this->service_name,'room_category' =>$this->room_category,'charges_cash' =>$this->charges_cash,'charges_cashless' =>$this->charges_cashless,])->andFilterWhere(['LIKE', 'serviceName.services', $this->getAttribute('serviceName.services')]);返回 $dataProvider;}}

在我的 Gridview 中,它是这样设置的:

<预><代码>['属性'='服务名称','value'=>'serviceName.services',],

正确显示相关模型中的服务名称.

我看不出我做错了什么,但是服务属性的过滤器字段根本没有显示.

解决方案

实际上比看起来要简单得多.

  1. column_name 添加到安全属性.注意:这应该是关系名称

  2. 使用查询添加连接 - 就像 - $query->joinWith(['serviceName','roomCategory']);

  3. 添加过滤条件,如:

    ->andFilterWhere(['like', 'services.services', $this->service_name])->andFilterWhere(['like', 'room_category.room_category', $this->room_category]);

  4. 如果想添加排序添加如下代码:

    $dataProvider->sort->attributes['service_name'] = ['asc' =>['services.services' =>SORT_ASC],'desc' =>['services.services' =>SORT_DESC],];$dataProvider->sort->attributes['room_category'] = ['asc' =>['room_category.room_category' =>SORT_ASC],'desc' =>['room_category.room_category' =>SORT_DESC],];

5 您还应该设置关系名称,例如 public $roomCategory

就是这样.相关表的排序和过滤都可以完美运行.

注意:删除相关列的默认验证,如整数和gii生成的默认过滤,否则会产生错误.

最新版本更新:

  • 不需要添加公共 $attribute.
  • 也不需要为关系添加安全属性.
  • 但是您当前模型中要过滤的属性是添加到必须的安全属性.
  • 最重要的是在您的 gridview 中,相关属性必须采用闭包格式.

就是例子

<预><代码>['attribute=''attribute_name','值=函数($数据){返回 $data->relationname->related_table_attribute_name}],

请记住,您正在使用 relation_name.related_table_attribute_name 过滤器不知何故对我不起作用.

I am trying to setup the filter for related model in Yii2's GridView widget, but I am keep getting the error like the filter value must be an integer.

I have followed this question. Now, I have a two models Services.php and ServiceCharge.php.

In ServiceCharge.php the relation is setup like:

public function getServiceName()
    {
        return $this->hasOne(Services::className(),['id'=>'service_name']);
    }

In the ServiceChargeSearch.php the code is like this:

<?php

namespace appmodels;

use Yii;
use yiiaseModel;
use yiidataActiveDataProvider;
use appmodelsServiceCharges;

/**
 * ServiceChargesSearch represents the model behind the search form about `appmodelsServiceCharges`.
 */
class ServiceChargesSearch extends ServiceCharges
{
    /**
     * @inheritdoc
     */
    public function attributes()
    {
        // add related fields to searchable attributes
      return array_merge(parent::attributes(), ['serviceName.services']);

    }
    public function rules()
    {
        return [
            [['id'], 'integer'],
            [['charges_cash', 'charges_cashless'], 'number'],
            [['id', 'serviceName.services', 'room_category'], 'safe'],
        ];
    }

    /**
     * @inheritdoc
     */
    public function scenarios()
    {
        // bypass scenarios() implementation in the parent class
        return Model::scenarios();
    }

    /**
     * Creates data provider instance with search query applied
     *
     * @param array $params
     *
     * @return ActiveDataProvider
     */
    public function search($params)
    {
        $query = ServiceCharges::find();

        $dataProvider = new ActiveDataProvider([
            'query' => $query,
        ]);
        $dataProvider->sort->attributes['serviceName.services'] = [
        'asc' => ['serviceName.services' => SORT_ASC],
        'desc' => ['serviceName.services' => SORT_DESC],
        ];

$query->joinWith(['serviceName']); 

        $this->load($params);

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

        $query->andFilterWhere([
            'id' => $this->id,
           // 'service_name' => $this->service_name,
            'room_category' => $this->room_category,
            'charges_cash' => $this->charges_cash,
            'charges_cashless' => $this->charges_cashless,
        ])
      ->andFilterWhere(['LIKE', 'serviceName.services', $this->getAttribute('serviceName.services')]);

        return $dataProvider;
    }
}

and in my Gridview it is setup like this:

[
                'attribute'=>'service_name',
                'value'=>'serviceName.services',

            ],

Which is showing the services name from the related model correctly.

I am not able to see what I am doing wrong, but the filter field for the attribute for service is not showing at all.

解决方案

Actually it is much simpler than it seems.

  1. add the column_name to safe attribute. Note: this should be relation Name

  2. add the join with query - like - $query->joinWith(['serviceName','roomCategory']);

  3. add the filter condition like:

    ->andFilterWhere(['like', 'services.services', $this->service_name])
    ->andFilterWhere(['like', 'room_category.room_category', $this->room_category]);
    

  4. if like to add sorting add the code like:

    $dataProvider->sort->attributes['service_name'] = [
        'asc'  => ['services.services' => SORT_ASC],
        'desc' => ['services.services' => SORT_DESC],
    ];
    $dataProvider->sort->attributes['room_category'] = [
        'asc'  => ['room_category.room_category' => SORT_ASC],
        'desc' => ['room_category.room_category' => SORT_DESC],
    ];
    

5 you should also set the relation name say public $roomCategory

That's it. Both sorting and filtering for related table works perfectly.

Note: Remove default validation like integer for related column and default filtering generated by gii otherwise it will generate an error.

Update on Latest version:

  • Adding Public $attribute is not needed.
  • Adding safe attribute for relation is also not needed.
  • but the attribute in your current model, which you want filter is to added to safe attribute that is a must.
  • and most importantly in your gridview, the related attribute has to be in closure format.

that is example

[
'attribute=>'attribute_name',
'value=function($data){
     return $data->relationname->related_table_attribute_name
}
],

remember it you are using relation_name.related_table_attribute_name filter somehow doesn't work for me.

相关文章