template - PHP, Yii2 GridView filtrando en valor relacional
yii2 gridview template (3)
Siguiendo de esto:
Yii2 ¿cómo funciona search () en SearchModel?
Me gustaría poder filtrar una columna GridView
de datos relacionales. Esto es lo que quiero decir:
Tengo dos tablas, TableA
y TableB
. Ambos tienen modelos correspondientes generados usando Gii. TableA
tiene una clave externa a un valor en TableB
, como este:
TableA
attrA1, attrA2, attrA3, TableB.attrB1
TableB
attrB1, attrB2, attrB3
attrA1 y attrB1 son las claves primarias de sus tablas correspondientes.
Ahora, tengo un Yii2 GridView
de attrA2
, attrA3
y attrB2
. Tengo un filtro de trabajo en attrA2
y attrA3
para poder buscar en los valores de columna. También tengo una clasificación de trabajo para estas dos columnas, simplemente haciendo clic en el encabezado de la columna. Me gustaría poder agregar este filtrado y clasificación en attrB2
también.
Mi modelo TableASearch
ve así:
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;
}
En mi modelo TableA
, establezco el valor relacionado como este
public $relationalValue;
public function afterFind(){
$b = TableB::find([''attrB1'' => $this->attrB1]);
$this->relationalValue = $b->relationalValue;
}
Aunque probablemente no sea la mejor manera de hacerlo. Creo que tengo que usar $ relationalValue en algún lugar de mi función de búsqueda, pero no estoy seguro de cómo. Del mismo modo, me gustaría poder ordenar por esta columna también, al igual que puedo para attrA2
y AttrA3
haciendo clic en el enlace del encabezado`. Cualquier ayuda sería apreciada. Gracias.
Esto se basa en la descripción en la guide . El código base para el SearchModel proviene del generador de código Gii. Esto también se supone que $ this-> TableB se ha configurado utilizando la relación hasOne()
o hasMany()
. Ver este doc .
1. Configurar el modelo de búsqueda
En el modelo TableASearch
agregar:
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'']
];
}
Luego, en TableASearch->search()
agregue (antes de $this->load()
):
$dataProvider->sort->attributes[''TableB.attrB1''] = [
''asc'' => [''TableB.attrB1'' => SORT_ASC],
''desc'' => [''TableB.attrB1'' => SORT_DESC],
];
$query->joinWith([''TableB'']);
Luego, la búsqueda real de sus datos (debajo de $this->load()
):
$query->andFilterWhere([''like'',''TableB.attrB1'',$this->getAttribute(''TableB.attrB1''));
2. Configurar GridView
Añade a tu vista:
echo GridView::widget([
''dataProvider'' => $dataProvider,
''filterModel'' => $searchModel,
''columns'' => [
/* Other columns */
''TableB1.attrB1'',
/* Other columns */
]
]);
Estoy atascado con este problema también, y mi solución es bastante diferente. Tengo dos modelos simples:
Libro:
class Book extends ActiveRecord
{
....
public static function tableName()
{
return ''books'';
}
public function getAuthor()
{
return $this->hasOne(Author::className(), [''id'' => ''author_id'']);
}
Y Autor:
class Author extends ActiveRecord
{
public static function tableName()
{
return ''authors'';
}
public function getBooks()
{
return $this->hasMany(Book::className(), [''author_id'' => ''id'']);
}
Pero mi lógica de búsqueda está en un modelo diferente. Y no encontré cómo puedo implementar la búsqueda sin crear un campo adicional author_first_name
. Así que esta es mi solución:
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;
}
}
Esto es para crear el alias de la tabla: function($query) { $query->from([''author'' => ''authors'']);}
Y el código de GridView es:
<?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''],
],
]); ?>
Apreciaré cualquier crítica y consejo.
Filtrar una vista de cuadrícula por una columna es muy fácil en Yii 2.0. Agregue el atributo de filtro a una columna de vista de cuadrícula que tenga valores de búsqueda, como en:
[
"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",
],