有一个显示的小部件GridView,包裹在Pjax. 网格有分页。页面上可以有许多这样的小部件,当您单击页面上的任何按钮时,可以加载一个模式窗口,其中将有更多的内容与另一组这些小部件。
如果仅在常规页面上或仅在模式窗口中存在小部件,则没有问题,因为容器Pjax和容器的标识符GridView是自动生成的(从头开始)并且分页在它们上起作用。
问题:当两者都存在时 - 在模态窗口中,标识符再次从零开始(由于 PHP 的特殊性和对服务器的新请求)并且当您在模态窗口中单击分页时 - 值会发生变化在“正常”中,但在模态中,一切都到位。
解决方案:为所有内容制作自己的 id 生成器。但同样,由于 PHP 的工作方式,您必须将会话用作存储和他妈的拐杖。我附上下面的工作代码(主要方法是init())。
问题:如何将这个最糟糕的代码改写成更合适的代码?或许提示出现问题的正常决定,比较优雅。
小部件代码:
class MyWidget extends Widget {
public $instanceId = 0;
private static $modalInstancesStorage = [];
/**
* {@inheritdoc}
* @internal
*/
public static $counter = 0;
/**
* {@inheritdoc}
*/
public static $autoIdPrefix = 'dc';
// Другие свойства
public function init() {
parent::init();
/*
* Этот блок для отслеживания вида запроса
* и генерирования идентификатора на основе этих данных.
*/
$request = \Yii::$app->request;
$isAjax = $request->isAjax;
$isPjax = $request->headers->get('x-pjax');
$containerIdParts = explode('-', $request->headers->get('x-pjax-container'));
$containerIdNumber = end($containerIdParts);
$id = 0;
if (!$this->instanceId)
$id = $this->getId();
if ($isAjax && !$isPjax) {
$id .= '1000';
self::$modalInstancesStorage = \Yii::$app->session->get('myWidgetModal') ?? [];
self::$modalInstancesStorage[$id] = serialize($this);
\Yii::$app->session->set('myWidgetModal', self::$modalInstancesStorage);
}
if (strpos($containerIdNumber, '1000') !== false) {
self::$modalInstancesStorage = \Yii::$app->session->get('myWidgetModal');
$objectAsArray = (array)unserialize(self::$modalInstancesStorage[$containerIdNumber]);
foreach($objectAsArray as $key => $value) {
try {
$this->$key = $value;
} catch (UnknownPropertyException $e) {
continue;
}
}
$id = $containerIdNumber;
}
$this->instanceId = $id;
}
public function run() {
$query = \Yii::createObject($this->srcModel)::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => [
'forcePageParam' => false,
'pageSizeParam' => false,
'pageSize' => 3
]
]);
return $this->render('widget-template', [
'instanceId' => $this->instanceId,
// Другие переменные
]);
}
}
表现:
<?php Pjax::begin(['id' => 'widget-grid-view-pjax-' . $instanceId]); ?>
<?= GridView::widget([
'id' => 'my-grid-view-' . $instanceId,
'dataProvider' => $dataProvider,
'columns' => $gridColumns,
]); ?>
<?php Pjax::end(); ?>
我什至将代码复制到编辑器中以理解这个想法:)也许我没有足够的数据来完全理解图片,但是,即使是这段代码,也可以预测应用程序进一步开发中的地狱般的痛苦。
我建议你尝试这样做:
结果,我们得到了一个干净的小部件,一个用于定义 ID 的单独类,我们将在调用小部件时设置它(ID)。在 init() 中的小部件中,剩下的就是调用 setId();。
PS:我还是不明白为什么要序列化一个对象并保存。
想出了一个更短的解决方案。
使用普通解决方案(不在小部件中)
id,控制器操作行会自动添加到 pjax 和 gridview。原来是这样的контроллер-экшн-p0。因此,常规页面没有冲突。仅适用于没有控制器和方法调用的小部件。因此,如何分析当前的出路,request并在此基础上按照相同的原理形成一个标识符。