Yii2使用viaTable关系在GridView中进行排序和过滤

时间:2016-01-20 08:29:29

标签: gridview yii2 relation

我无法弄清楚如何使用关系表在Yii2中进行过滤和排序。

我有3个桌子,因为链接可以有多个国家/地区。我想出了如何将它保存到links_countries表中。

Links     Countries  LinksCountries
link_id   country    link_id
country              country

链接和国家/地区在链接模型

中与此关系相关联
    public function getManyCountries()
    {
        return $this->hasMany(Countries::className(), ['country' => 'country'])->viaTable('links_countries', ['links_id' => 'links_id']);
    }

在index.php GridView中我有

[
                'label' => 'Countries',
                'attribute' => 'linksCountries.country',
                'value' => function ($model) {
                    $countries = ArrayHelper::map($model->manyCountries, 'country', 'country_name');
                    return implode(', ', $countries);
                 },
                'format' => 'raw'

            ],

导致这样的网格

enter image description here

正如您所看到的,ID 1034的链接有多个国家/地区,但过滤器无法正常工作。 那么如何像这样显示网格?

Link ID    Country     Link
1034       Andorra     linkname1
1034       Kosovo      linkname1

我尝试了这种关系

public function getLinksCountries()
    {
        return $this->hasMany(LinksCountries::className(), ['links_id' => 'links_id']);
    }

并在LinksSearch模型中

$dataProvider = new ActiveDataProvider([
    //'query' => $query,
    'query' => $this->getLinksCountries(),
]);

但它似乎不起作用。

2 个答案:

答案 0 :(得分:3)

因此,解决方案是基于LinksCountries模型显示网格并从Links模型获取值。

<强> LinksCountries.php

<?php

namespace common\models;

use Yii;

class LinksCountries extends \yii\db\ActiveRecord
    {

    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'links_countries';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['links_id', 'country'], 'required'],
            [['links_id'], 'integer'],
            [['modified_date', 'created_date'], 'safe'],
            [['country'], 'string', 'max' => 3],
            [['modified_by', 'created_by'], 'string', 'max' => 64]
        ];
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getManyCountries()
    {
        return $this->hasOne(Countries::className(), ['country' => 'country']);
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getLinks()
    {
        return $this->hasOne(Links::className(), ['links_id' => 'links_id']);
    }

    public function getCountryName() {
        return $this->country->country_name;
    }

    public function getLinkName() {
        return $this->links->link;
    }

    public function getShortDescription() {
        return $this->links->short_description;
    }
}

<强> LinksCountriesSearch.php

<?php

namespace common\models;

use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use common\models\LinksCountries;

class LinksCountriesSearch extends LinksCountries
{
    public $linkName;
    public $shortDescription;

    public function rules()
    {
        return [
            [['links_countries_id', 'links_id'], 'integer'],
            [['country', 'modified_by', 'modified_date', 'created_by', 'created_date', 'linkName', 'shortDescription'], '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 = LinksCountries::find();

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

        $dataProvider->sort->attributes['linkName'] = [
            'asc' => ['links.link' => SORT_ASC],
            'desc' => ['links.link' => SORT_DESC],
        ];

        $dataProvider->sort->attributes['shortDescription'] = [
            'asc' => ['links.short_description' => SORT_ASC],
            'desc' => ['links.short_description' => SORT_DESC],
        ];

        $query->joinWith('links');
        $query->joinWith('manyCountries');     

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

        $query->andFilterWhere([
            'links_countries_id' => $this->links_countries_id,
            'links.links_id' => $this->links_id,
            'modified_date' => $this->modified_date,
            'created_date' => $this->created_date,
        ]);

        $query->andFilterWhere(['like', 'countries.country_name', $this->country])
            ->andFilterWhere(['ilike', 'links.link', $this->linkName])
            ->andFilterWhere(['ilike', 'links.short_description', $this->shortDescription])
            ->andFilterWhere(['like', 'modified_by', $this->modified_by])
            ->andFilterWhere(['like', 'created_by', $this->created_by]);

        return $dataProvider;
    }
}

<强>的index.php

use yii\helpers\ArrayHelper;
use common\models\Countries;

echo GridView::widget([
    'dataProvider'=> $dataProvider,
    'filterModel' => $searchModel,
    'columns' => [
        [
                'attribute' => 'links_id',
                'width'=>'50px',
            ],
            [
                'attribute' => 'country',
                'value' => 'manyCountries.country_name',
                'vAlign'=>'middle',
                'width'=>'200px',
                'filterType'=>GridView::FILTER_SELECT2,
                    'filter'=> ArrayHelper::map(Countries::find()->orderBy('country_name')->asArray()->all(), 'country_name', 'country_name'),
                    'filterWidgetOptions'=>[
                        'pluginOptions'=>['allowClear'=>true],
                    ],
                'filterInputOptions'=>['placeholder'=>'Select country'],
                'format'=>'raw',
            ],
            [
                'attribute' => 'linkName',
                'format' => 'raw',
                'value' => function ($model) {
                    return Html::a($model->linkName, $model->linkName, ['target'=>'_blank']);
                },
            ],
            'shortDescription',
    ],

]);

答案 1 :(得分:1)

要在modelSearch中添加过滤(和排序)功能,您应该将相关字段添加到dataProvider设置排序部分(默认模型的字段默认具有过滤器,而对于相关字段,您必须使用setSort <添加过滤器< / em>的)

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

$dataProvider->setSort([
  'attributes' => [
      'your_new_attribute' => [
         'asc' => ['your_related_table_name.your_field' => SORT_ASC],
         'desc' => ['your_related_table_name.your_field' => SORT_DESC],
          'label' => 'Your_label',
          'default' => SORT_ASC
      ],  
  .....

并且要添加defaultOrder,只需添加此

的条件即可
$dataProvider->setSort([
  'attributes' => [
      'your_new_attribute' => [
         'asc' => ['your_related_table_name.your_field' => SORT_ASC],
         'desc' => ['your_related_table_name.your_field' => SORT_DESC],
          'label' => 'Your_label',
          'default' => SORT_ASC
      ],  
  'defaultOrder' => [ 'your_new_attribute' => SORT_DESC ],
   ........