Andrey
Andrey

Reputation: 1110

Yii 1.1 session sometimes won't store value

I'm getting a weird behavior I can't fully explain. Consider this controller code:

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));
}

So first I create the order, then if creation is successful, there is a redirect to the confirmation page. Order id is saved to the session so the customer can see the order they created. Why can't I make a redirect to "confirm($order_id)" page? Because 1. Order contains user submitted data and it can't be public, only user created that order can view it on the confirmation page, and 2. There is no authentication there, users are not required to log in.

The weird thing is, most of the time it works fine, but sometimes (1 time out of 5 approx) the order id is not saved in session. If the session is fresh, then it will end up showing 404. If it's not and you create several orders, it will evenually show the previous order data (next order is saved fine).

I would suggest that something is wrong with the session component itself (I'm using CDbHttpSession). But everything else (session related stuff) is working fine on the site (backend auth never fails, flash messages always show up).

Any ideas where should I look?

Upvotes: 1

Views: 858

Answers (1)

Andrey
Andrey

Reputation: 1110

Okay, it appears pretty obvious now. The reason was classic session race condition: session auto start, performAjaxValidation reads session before order_id is set, then saves session without order_id after order_id is set but before actionConfirm is called. Native PHP sessions are blocking so this situation won't happen but db sessions are not.

Upvotes: 1

Related Questions