Исходя из этого:
Yii2 Как работает поиск () в SearchModel?
Я хотел бы иметь возможность фильтровать столбец GridView
реляционных данных. Это то, что я имею в виду:
У меня есть две таблицы, TableA
и TableB
. Оба имеют соответствующие модели, сгенерированные с использованием Gii. TableA
имеет внешний ключ для значения в TableB
, например:
TableA attrA1, attrA2, attrA3, TableB.attrB1 TableB attrB1, attrB2, attrB3
attrA1 и attrB1 являются первичными ключами соответствующих таблиц.
Теперь у меня есть Yii2 GridView
attrA2
, attrA3
и attrB2
. У меня есть рабочий фильтр на attrA2
и attrA3
чтобы я мог искать значения столбцов. У меня также есть рабочий вид для этих двух столбцов – просто щелкнув заголовок столбца. Я хотел бы иметь возможность добавлять эту фильтрацию и сортировку на attrB2
тоже.
Моя модель TableASearch
выглядит так:
public function search($params){ $query = TableA::find(); $dataProvider = new ActiveDataProvider([ 'query' => $query, ]); if (!($this->load($params) && $this->validate())) { return $dataProvider; } $this->addCondition($query, 'attrA2'); $this->addCondition($query, 'attrA2', true); $this->addCondition($query, 'attrA3'); $this->addCondition($query, 'attrA3', true); return $dataProvider; }
В моей модели TableA
я устанавливаю соответствующее значение следующим образом
public $relationalValue; public function afterFind(){ $b = TableB::find(['attrB1' => $this->attrB1]); $this->relationalValue = $b->relationalValue; }
Хотя это, вероятно, не лучший способ сделать это. Я думаю, что мне нужно использовать $ relationalValue где-то в моей функции поиска, но я не уверен, как это сделать. Аналогично, я хотел бы иметь возможность сортировать по этому столбцу тоже – так же, как я могу для attrA2
и AttrA3
, нажав на ссылку заголовка`. Любая помощь будет оценена по достоинству. Благодарю.
Фильтрация сетки в столбце в Yii 2.0 проста. Добавьте атрибут фильтра в столбец gridview со значениями поиска, как показано ниже:
[ "class" => yii\grid\DataColumn::className(), "attribute" => "status_id", 'filter' => ArrayHelper::map(Status::find()->orderBy('name')->asArray()->all(), 'id', 'name'), "value" => function($model){ if ($rel = $model->getStatus()->one()) { return yii\helpers\Html::a($rel->name,["crud/status/view", 'id' => $rel->id,],["data-pjax"=>0]); } else { return ''; } }, "format" => "raw", ],
Это основано на описании в руководстве . Базовый код для SearchModel поступает из генератора кода Gii. Это также предполагает, что $ this-> TableB был настроен с использованием отношения hasOne()
или hasMany()
. См. Этот документ .
1. Настроить поисковую модель
В модели TableASearch
добавьте:
public function attributes() { // add related fields to searchable attributes return array_merge(parent::attributes(), ['TableB.attrB1']); } public function rules() { return [ /* your other rules */ [['TableB.attrB1'], 'safe'] ]; }
Затем в TableASearch->search()
добавьте (до $this->load()
):
$dataProvider->sort->attributes['TableB.attrB1'] = [ 'asc' => ['TableB.attrB1' => SORT_ASC], 'desc' => ['TableB.attrB1' => SORT_DESC], ]; $query->joinWith(['TableB']);
Затем фактический поиск ваших данных (ниже $this->load()
):
$query->andFilterWhere(['like','TableB.attrB1',$this->getAttribute('TableB.attrB1'));
2. Настройте GridView
Добавить к вашему мнению:
echo GridView::widget([ 'dataProvider' => $dataProvider, 'filterModel' => $searchModel, 'columns' => [ /* Other columns */ 'TableB1.attrB1', /* Other columns */ ] ]);
Я тоже застрял в этой проблеме, и мое решение совсем другое. У меня две простые модели:
Книга:
class Book extends ActiveRecord { .... public static function tableName() { return 'books'; } public function getAuthor() { return $this->hasOne(Author::className(), ['id' => 'author_id']); }
И Автор:
class Author extends ActiveRecord { public static function tableName() { return 'authors'; } public function getBooks() { return $this->hasMany(Book::className(), ['author_id' => 'id']); }
Но моя логика поиска находится в другой модели. И я не нашел, как я могу реализовать поиск без создания дополнительного поля author_first_name
. Итак, это мое решение:
class BookSearch extends Model { public $id; public $title; public $author_first_name; public function rules() { return [ [['id', 'author_id'], 'integer'], [['title', 'author_first_name'], 'safe'], ]; } public function search($params) { $query = Book::find()->joinWith(['author' => function($query) { $query->from(['author' => 'authors']);}]); $dataProvider = new ActiveDataProvider([ 'query' => $query, 'pagination' => array('pageSize' => 50), 'sort'=>[ 'attributes'=>[ 'author_first_name'=>[ 'asc' => ['author.first_name' => SORT_ASC], 'desc' => ['author.first_name' => SORT_DESC], ] ] ] ]); if (!($this->load($params) && $this->validate())) { return $dataProvider; } .... $query->andWhere(['like', 'author.first_name', $this->author_first_name]); return $dataProvider; } }
Это для создания псевдонима таблицы: function($query) { $query->from(['author' => 'authors']);}
И код GridView:
<?php echo GridView::widget([ 'dataProvider' => $dataProvider, 'filterModel' => $searchModel, 'columns' => [ [ 'attribute' => 'id', 'filter' => false, ], [ 'attribute' => 'title', ], [ 'attribute' => 'author_first_name', 'value' => function ($model) { if ($model->author) { $model->author->getFullName(); } else { return ''; } }, 'filter' => true, ], ['class' => 'yii\grid\ActionColumn'], ], ]); ?>
Буду признателен за любые критические замечания и советы.