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 会话正在阻塞,因此不会发生这种情况,但数据库会话不会。