Yii 1.1 会话有时不会存储值
Yii 1.1 session sometimes won't store value
我遇到了一个我无法完全解释的奇怪行为。考虑这个控制器代码:
public function actionCreate()
{
$order = new Order();
$this->performAjaxValidation($order, null, 'order-form');
if (isset($_POST['Order'])) {
$order->attributes = $_POST['Order'];
if ($order->save()) {
Yii::app()->session['order_id'] = $order->id;
$this->redirect('confirm');
}
}
$this->render('create', array('order' => $order));
}
public function actionConfirm()
{
$order_id = Yii::app()->session['order_id'];
if(!$order_id) {
throw new CHttpException(404, 'Order not found');
}
$order = $this->loadModel($order_id);
$this->render('confirm', array('order' => $order));
}
所以我首先创建订单,然后如果创建成功,就会重定向到确认页面。订单 ID 保存到会话中,以便客户可以看到他们创建的订单。为什么我不能重定向到 "confirm($order_id)" 页面?因为1.订单包含用户提交的数据,不能是public,只有创建该订单的用户才能在确认页面查看,2.那里没有认证,用户不需要登录。
奇怪的是,大多数时候它工作正常,但有时(大约 5 次中有 1 次)订单 ID 没有保存在会话中。如果会话是新鲜的,那么它最终会显示 404。如果它不是并且你创建了多个订单,它最终会显示以前的订单数据(下一个订单保存得很好)。
我建议会话组件本身有问题(我正在使用 CDbHttpSession)。但是网站上的其他一切(与会话相关的东西)都运行良好(后端身份验证永远不会失败,总是会显示闪存消息)。
有什么想法我应该去哪里看?
好的,现在看起来很明显了。原因是经典会话竞争条件:会话自动启动,performAjaxValidation 在设置 order_id 之前读取会话,然后在设置 order_id 之后但在调用 actionConfirm 之前保存没有 order_id 的会话。本机 PHP 会话正在阻塞,因此不会发生这种情况,但数据库会话不会。
我遇到了一个我无法完全解释的奇怪行为。考虑这个控制器代码:
public function actionCreate()
{
$order = new Order();
$this->performAjaxValidation($order, null, 'order-form');
if (isset($_POST['Order'])) {
$order->attributes = $_POST['Order'];
if ($order->save()) {
Yii::app()->session['order_id'] = $order->id;
$this->redirect('confirm');
}
}
$this->render('create', array('order' => $order));
}
public function actionConfirm()
{
$order_id = Yii::app()->session['order_id'];
if(!$order_id) {
throw new CHttpException(404, 'Order not found');
}
$order = $this->loadModel($order_id);
$this->render('confirm', array('order' => $order));
}
所以我首先创建订单,然后如果创建成功,就会重定向到确认页面。订单 ID 保存到会话中,以便客户可以看到他们创建的订单。为什么我不能重定向到 "confirm($order_id)" 页面?因为1.订单包含用户提交的数据,不能是public,只有创建该订单的用户才能在确认页面查看,2.那里没有认证,用户不需要登录。
奇怪的是,大多数时候它工作正常,但有时(大约 5 次中有 1 次)订单 ID 没有保存在会话中。如果会话是新鲜的,那么它最终会显示 404。如果它不是并且你创建了多个订单,它最终会显示以前的订单数据(下一个订单保存得很好)。
我建议会话组件本身有问题(我正在使用 CDbHttpSession)。但是网站上的其他一切(与会话相关的东西)都运行良好(后端身份验证永远不会失败,总是会显示闪存消息)。
有什么想法我应该去哪里看?
好的,现在看起来很明显了。原因是经典会话竞争条件:会话自动启动,performAjaxValidation 在设置 order_id 之前读取会话,然后在设置 order_id 之后但在调用 actionConfirm 之前保存没有 order_id 的会话。本机 PHP 会话正在阻塞,因此不会发生这种情况,但数据库会话不会。