Добрый день, сообщество.
Имеется представление, которое содержит большое количество виджетов (внутри которых GridView, форма для добавления новых записей и для редактирования существующих). Каждый виджет связан со своей сущностью из агрегата.
Для простоты понимания представим следующий агрегат:
На странице информации о клиенте содержатся виджеты непосредственно для отображения и редактирования модели Customer, а также по одному виджету для каждой сущности CustomerEmail, CustomerPhone и т.д.
То, как это примерно выглядит, можно посмотреть по ссылке.
Сейчас всё это всё ещё работает, но с ростом количества сущностей агрегата (их уже больше 10) приобретает очень страшный вид в действии контроллера.
Весь этот интерфейс рендерится одним действием контроллера. В этом действии создаются провайдеры данных и объекты классов фильтрации для всех сущностей и затем передаются в рендер.
Чтобы переключить страницу или отсортировать какой нибудь один из множества GridView, происходит инстанцирование всех остальных провайдеров данных и классов фильтрации, которые не нужны конкретно для сортировки какого-то одного GridView.
Это все вызывает дикий оверхед, который хотелось бы оптимизировать.
Было рассмотрено решение HMVC, но, к сожалению, не совсем понятно, как это использовать в Yii2.
Может быть есть какие-то рекомендации или практики по организации подобных иерархических интерфейсов?
Я хочу добиться такой организации кода, при которой для работы с одной сущностью (например, пагинация таблицы телефонов или добавление нового телефона) не придется инстанцировать десяток совершенно не нужных провайдеров и фильтров.
На ум приходит только организация отдельных контроллеров для каждого виджета, но я не нашел, как это можно реализовать в Yii2.
Организация иерархического представления (HMVC)
- denisbondar
- Сообщения: 31
- Зарегистрирован: 2015.10.12, 19:34
-
- Сообщения: 10
- Зарегистрирован: 2017.04.24, 20:06
- denisbondar
- Сообщения: 31
- Зарегистрирован: 2015.10.12, 19:34
Re: Организация иерархического представления (HMVC)
Возможно.
Помогите мне с этим пожалуйста. Покажите пример. Я не нашел ничего, чтобы внесло ясность, как это использовать в моем случае.
Набросал немного кода, чтобы диалог был более предметным.
Помогите мне с этим пожалуйста. Покажите пример. Я не нашел ничего, чтобы внесло ясность, как это использовать в моем случае.
Набросал немного кода, чтобы диалог был более предметным.
Re: Организация иерархического представления (HMVC)
В контроллере просмотра клиента ищем только его:
В представлении выводим все виджеты:
Каждый виджет формирует вывод и форму, подставляя свои route:
в своём представлении с action:
И для всех вещей делаем отдельные экшны:
с простым выводом одного виджета:
В итоге всё выводится на одной странице, но все запросы из Pjax и форм летят в свои отдельные экшны, перегружающие только свой Pjax-блок.
Код: Выделить всё
class SiteController extends Controller
{
public function actionClient($id)
{
$client = $this->findModel($id);
$this->render('index', [
'client' => $client,
]);
}
}
Код: Выделить всё
<?= Html::encode($client->name) ?>
<?= ClientAddressesWidget::widget(['client' => $client]) ?>
<?= ClientPhonesWidget::widget(['client' => $client]) ?>
<?= ClientEmailsWidget::widget(['client' => $client]) ?>
Код: Выделить всё
class ClientAddressesWidget extends Widget
{
public $client;
public $model;
public function run()
{
$search = new AddressSearch();
$provider = $search->search($this->client->id, Yii::$app->request->queryParams);
$provider->sort->route = 'client/addresses',
$provider->pagination->route = 'client/addresses',
$model = $this->model ?: new Address();
$this->render('addresses', [
'search' => $search,
'provider' => $provider,
'model' => $model,
'client' => $this->client,
]);
}
}
Код: Выделить всё
<?= Pjax::begin(['id' => 'client-addresses']) ?>
<?= GridView::widget([
'dataProvider' => $provider,
...
]) ?>
<?php $form = ActiveForm::begin([
'action' => ['addresses', 'id' => $client->id],
'options' => ['data-pjax' => true],
]) ?>
...
<?php ActiveForm::end() ?>
<?php Pjax::end() ?>
Код: Выделить всё
class SiteController extends Controller
{
public function actionAddresses($id)
{
$client = $this->findModel($id);
$model = new Address();
$model->client_id = $client->id;
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['client', 'id' => $id]);
}
return $this->render('addresses', [
'client' => $client,
'model' => $model,
]);
}
}
Код: Выделить всё
<?= ClientAddressesWidget::widget(['client' => $client, 'model' => $model]) ?>
- denisbondar
- Сообщения: 31
- Зарегистрирован: 2015.10.12, 19:34
Re: Организация иерархического представления (HMVC)
Огромное спасибо, Дмитрий!
Кажется, это именно то, чего я пытался добиться. Все оказалось намного проще. Я залез в дебри, совсем не в ту степь, и уже не мог самостоятельно вернуться назад.
Большое спасибо!
На всякий случай, вдруг кому будет полезно, код можно посмотреть здесь: https://github.com/denisbondar/yii2-hmvc-test
Понемногу дополню пример различной функциональностью.
Кажется, это именно то, чего я пытался добиться. Все оказалось намного проще. Я залез в дебри, совсем не в ту степь, и уже не мог самостоятельно вернуться назад.
Большое спасибо!
На всякий случай, вдруг кому будет полезно, код можно посмотреть здесь: https://github.com/denisbondar/yii2-hmvc-test
Понемногу дополню пример различной функциональностью.