Yii2更新后重定向至分页原页面的问题及异常场景咨询
解决Yii2更新记录后重定向至原分页页并避免新标签页干扰的问题
这个问题我之前在项目里也遇到过,确实挺头疼的——全局的returnUrl很容易被其他操作覆盖,尤其是用户开新标签页操作其他控制器的场景。下面给你两个靠谱的解决方案,亲测有效:
方案一:通过URL参数传递原分页地址(简单直接)
核心思路是把原索引页的分页信息直接作为参数传给更新页面,完全不依赖全局session存储,从根源上避免新标签页操作的干扰。
步骤1:修改GridView的更新按钮,传递原页面URL
在你的索引页GridView配置中,自定义更新按钮,把当前页面的完整URL(包含分页参数)编码后作为参数传递:
use yii\helpers\Html; // ... 其他GridView配置 'columns' => [ // ... 其他列 [ 'class' => 'yii\grid\ActionColumn', 'template' => '{update} {delete}', 'buttons' => [ 'update' => function ($url, $model) { // 获取当前页面的完整URL(包含?page=3这类分页参数) $currentIndexUrl = Yii::$app->request->url; // 把原URL编码后作为参数加到更新链接里 return Html::a( '<span class="glyphicon glyphicon-pencil"></span>', ['update', 'id' => $model->id, 'returnUrl' => urlencode($currentIndexUrl)], ['title' => Yii::t('app', 'Update')] ); }, ], ], ],
步骤2:在Update Action中处理跳转
更新操作完成后,直接使用传递过来的returnUrl跳转:
public function actionUpdate($id) { $model = $this->findModel($id); // 获取传递的原页面URL,默认值设为索引页 $returnUrl = Yii::$app->request->get('returnUrl', ['index']); if ($model->load(Yii::$app->request->post()) && $model->save()) { // 解码URL并跳转 return $this->redirect(urldecode($returnUrl)); } return $this->render('update', [ 'model' => $model, 'returnUrl' => $returnUrl, // 如果需要在视图里用的话可以传递 ]); }
方案二:用模型ID绑定的Session存储(适合敏感场景)
如果担心URL参数过长或者不想暴露原页面信息,可以用和模型ID绑定的Session键来存储原分页地址,每个更新的模型有独立的存储,不会被其他操作覆盖。
步骤1:在Update Action中存储/读取Session
public function actionUpdate($id) { $model = $this->findModel($id); $sessionKey = "returnUrl_{$id}"; // 用模型ID作为Session键的一部分 // 首次进入更新页时,把传递的原URL存到Session if (Yii::$app->request->get('returnUrl') && !Yii::$app->session->has($sessionKey)) { Yii::$app->session->set($sessionKey, Yii::$app->request->get('returnUrl')); } // 从Session读取原URL,默认索引页 $returnUrl = Yii::$app->session->get($sessionKey, ['index']); if ($model->load(Yii::$app->request->post()) && $model->save()) { // 跳转后清除Session,避免后续干扰 Yii::$app->session->remove($sessionKey); return $this->redirect(urldecode($returnUrl)); } return $this->render('update', [ 'model' => $model, ]); }
步骤2:更新按钮的配置和方案一一致
同样需要在GridView的更新按钮中传递returnUrl参数,这里就不重复代码了。
为什么原来的全局ReturnUrl不行?
Yii的Yii::$app->user->returnUrl是全局的Session变量,任何调用setReturnUrl()的操作(比如很多控制器的默认index方法会设置)都会覆盖它。当用户在新标签页打开其他控制器的页面时,那个页面的操作会更新这个全局变量,导致你保存记录后跳转到错误的地址。
而上面的两种方案,要么把原地址和当前更新请求绑定(URL参数),要么用独立的Session键(和模型ID绑定),完全避开了全局变量的干扰。
内容的提问来源于stack exchange,提问作者Ivaylo Kostadinov
相关产品推荐
相关产品推荐

