Сегодня закончим тему GridView и доделаем начатое. С прошлого урока у нас осталась таблица пользователей с их данными, которую предстоит немного доработать: сделаем фильтрацию, сортировку и поиск по связным данным моделей.
Сейчас в тестовом проекте имеется вот такая таблица. Нетрудно заметить, что столбцы с местом работы и должностью юзеров не адаптированы под фильтр, сортировку и поиск:
Так-с, приступим. Для начала переходим к классу MemberSearch. В него необходимо добавить два публичных свойства: первое для места работы, второе для должности:
public string $org_name = '';
public string $worker_position = '';
Свойства можно, кстати, назвать как угодно.
В этом же классе есть метод rules(), в него необходимо вписать только что созданные свойства (org_name и worker_position):
public function rules() : array
{
return [
[ [ 'id', 'joined' ], 'integer' ],
[ [ 'name', 'org_name', 'worker_position' ], 'safe' ],
];
}
Точно такие же коррективы вносим и в класс Member для метода attributeLabels():
public function attributeLabels() : array
{
return [
'oid' => 'Место работы',
'name' => 'Имя',
'joined' => 'Дата регистрации',
'org_name' => 'Место работы',
'worker_position' => 'Должность',
];
}
И, пожалуй, это был единственный момент, который нужно было подправить в этом классе.
Теперь возвращаемся обратно к MemberSearch, ищем там метод search(), внутри которого находим строку:
$query = Member::find();
И меняем её на:
$query = Member::find()->joinWith( [
'worker' => function( $w )
{
$w->joinWith( 'organization' );
}
] );
Также стоит удостовериться в наличии связи getWorker() в классе Member:
public function getWorker() : \yii\db\ActiveQuery
{
return $this->hasOne( Worker::class, [ 'uid' => 'id' ] );
}
И в наличии связи getOrganization() в классе Worker:
public function getOrganization() : \yii\db\ActiveQuery
{
return $this->hasOne( Organization::class, [ 'id' => 'oid' ] );
}
Если их нет - добавьте. В противном случае работать ничего не будет.
Далее вновь возвращаемся к search() класса MemberSerach и в DataProvider добавляем сортировку:
$dataProvider = new \yii\data\ActiveDataProvider( [
'query' => $query,
'sort' => [
'attributes' => [
'name',
'joined',
'org_name' => [
'asc' => [ 'organizations.name' => SORT_ASC ],
'desc' => [ 'organizations.name' => SORT_DESC ],
],
'worker_position' => [
'asc' => [ 'workers.position' => SORT_ASC ],
'desc' => [ 'workers.position' => SORT_DESC ],
],
]
],
] );
Ну, и добавляем фильтры:
$query
->andFilterWhere( [ 'like', 'name', $this->name ] )
->andFilterWhere( [ 'like', 'organizations.name', $this->org_name ] )
->andFilterWhere( [ 'like', 'position', $this->worker_position ] );
Окей, с этим мы разобрались и в конечном итоге MemberSearch.php выглядит следующим образом:
<?php
namespace app\models;
class MemberSearch extends Member
{
public string $worker_position = '';
public string $org_name = '';
public function rules() : array
{
return [
[ [ 'id', 'joined' ], 'integer' ],
[ [ 'name', 'org_name', 'worker_position' ], 'safe' ],
];
}
public function scenarios() : array
{
return \yii\base\Model::scenarios();
}
public function search( $params ) : \yii\data\ActiveDataProvider
{
$query = Member::find()->joinWith( [
'worker' => function( $w )
{
$w->joinWith( 'organization' );
}
] );
$dataProvider = new \yii\data\ActiveDataProvider( [
'query' => $query,
'sort' => [
'attributes' => [
'name',
'joined',
'org_name' => [
'asc' => [ 'organizations.name' => SORT_ASC ],
'desc' => [ 'organizations.name' => SORT_DESC ],
],
'worker_position' => [
'asc' => [ 'workers.position' => SORT_ASC ],
'desc' => [ 'workers.position' => SORT_DESC ],
],
]
],
] );
$this->load( $params );
if ( !$this->validate() )
{
return $dataProvider;
}
$query
->andFilterWhere( [ 'like', 'name', $this->name ] )
->andFilterWhere( [ 'like', 'organizations.name', $this->org_name ] )
->andFilterWhere( [ 'like', 'position', $this->worker_position ] );
return $dataProvider;
}
}
Нам осталось всего-навсего поменять атрибуты в нужных столбцах таблицы в виде:
[
'attribute' => 'org_name',
'value' => function( $member )
{
return $member->worker->organization->name ?? '-';
},
],
[
'attribute' => 'worker_position',
'content' => function( $member )
{
return $member->worker->position ?? '-';
},
],
Вид index целиком:
<?php
/* @var $this yii\web\View */
/* @var $searchModel app\models\MemberSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="member-index">
<h1><?= \yii\helpers\Html::encode( $this->title ) ?></h1>
<p>
<?= \yii\helpers\Html::a( 'Добавить пользователя', [ 'create' ], [ 'class' => 'btn btn-success' ] ) ?>
</p>
<?php \yii\widgets\Pjax::begin() ?>
<?= \yii\grid\GridView::widget( [
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'layout' => '{items}{pager}',
'columns' => [
[
'attribute' => 'name',
'content' => function( $member )
{
return "<b>{$member->name}</b>";
},
],
[
'attribute' => 'joined',
'value' => function( $member )
{
return date( 'd.m.y', $member->joined );
},
],
[
'attribute' => 'org_name',
'value' => function( $member )
{
return $member->worker->organization->name ?? '-';
},
],
[
'attribute' => 'worker_position',
'content' => function( $member )
{
return $member->worker->position ?? '-';
},
],
[
'class' => \yii\grid\ActionColumn::class,
'urlCreator' => function( $action, \app\models\Member $model, $key, $index, $column )
{
return \yii\helpers\Url::toRoute( [ $action, 'id' => $model->id ] );
}
],
],
] ); ?>
<?php \yii\widgets\Pjax::end() ?>
</div>
И уже на этом завершающем этапе можно посмотреть на проделанную работу. Сортировка появилась, поля для поиска тоже.
Конец😉
Перед публикацией, советую ознакомится с правилами!
Нашли ошибку?
Вы можете сообщить об этом администрации.
Выделив текст нажмите CTRL+Enter