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

标签 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(),
]);

但似乎不起作用。

最佳答案

因此,解决方案是基于 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',
    ],

]);

关于gridview - Yii2 在 GridView 中使用 viaTable 关系进行排序和过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34894966/

相关文章:

html - Yii2 Krajee Select2 插件格式化

c# - GridView 页码间距?

c# - 获取gridview复选框

php - 在 View 中渲染数据时出现"Undefined variable"错误

yii2 - yii2 时区格式化程序中的问题

gridview - Yii2:动态模型属性

mysql - 在 mysql 中为产品和类别创建唯一的 url

php - 从带有外键的表中获取值

c# - GridView Asp .Net-根据同一列中第一个下拉列表的值更改第二个下拉列表的选定值

java - 如何在 Firebase 中存储 HashMap 以供离线使用