これから続く:
Yii2 SearchModelのsearch()はどのように機能しますか?
リレーショナルデータのGridView
列をフィルタリングできるようにしたいと思います。これは私が意味することです:
TableA
とTableB
の2つのテーブルがあります。どちらにも、Giiを使用して生成された対応するモデルがあります。 TableA
には、次のようにTableB
の値への外部キーがあります。
TableA
attrA1, attrA2, attrA3, TableB.attrB1
TableB
attrB1, attrB2, attrB3
attrA1とattrB1は、対応するテーブルの主キーです。
これで、Yii2 GridView
がattrA2
、attrA3
、attrB2
になりました。列の値を検索できるように、attrA2
とattrA3
に有効なフィルターがあります。また、列ヘッダーをクリックするだけで、これら2つの列の作業ソートもできます。このフィルタリングと並べ替えを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では、列でグリッドビューをフィルタリングするのはとても簡単です。以下のように、ルックアップ値を持つグリッドビュー列にフィルター属性を追加してください:
[
"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()
リレーションを使用して設定されていることも前提としています。これを見てください doc 。
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 */
]
]);
_
私もこの問題に悩まされており、私の解決策はかなり異なります。 2つの単純なモデルがあります。
本:
_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'],
],
]); ?>
_
どんな批評やアドバイスにも感謝します。