我得到了一个奇怪的行为,我无法完全解释。考虑一下这个控制器代码:
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将保存到会话中,以便客户可以查看他们创建的订单。为什么我无法重定向到"确认($ order_id)"页?因为1.订单包含用户提交的数据并且它不能公开,只有用户创建该订单才能在确认页面上查看它,并且2.没有认证,用户不需要登录。
奇怪的是,大部分时间它工作正常,但有时(大约5次约1次)订单ID不会保存在会话中。如果会话是新鲜的,那么它最终将显示404.如果不是并且您创建了多个订单,它将始终显示以前的订单数据(下一个订单保存正常)。
我会建议会话组件本身出错(我使用的是CDbHttpSession)。但其他一切(与会话相关的东西)在网站上运行正常(后端auth永远不会失败,闪存消息总会出现)。
我应该在哪里找到想法?
答案 0 :(得分:1)
好的,现在看来非常明显。原因是经典会话竞争条件:会话自动启动,performAjaxValidation在设置order_id之前读取会话,然后在设置order_id之后但在调用actionConfirm之前保存没有order_id的会话。本机PHP会话正在阻塞,因此这种情况不会发生,但数据库会话不会发生。