help with a transaction

After numerous different attempts to get this to work I need to come ask for help.

The goal is to have a transaction complete before a view file is rendered per the given controller. If the transaction fails I want the user to be redirected to the page they came from. I know it looks like I am only doing a single insert and would not require a transaction but this is way scaled back so I can test the concept then roll everything back in.

How would I roll this code for the transaction into the controller code for the view action?

transaction:


$connection = yii::app()->db;

$transaction=$connection->beginTransaction();

try 

{

	$sql1 = "INSERT INTO selection (UserId, ItemId t)

				VALUES(".Yii::app()->user->id.",".$model->ItemId;

		

	$connection->createCommand($sql1)->execute();

	

	$transaction->commit();

}

catch(Exception $e)

{

	$transaction->rollBack();

		$this->redirect(array('view', 'id' => $model->PreviousModelId));


} 

View file that I only want rendered upon successful completion of the transaction.


public function actionView($id) {

		$this->render('view', array(

			'model' => $this->loadModel($id, 'Item'),

		));

	}

EDIT: Change of approach needed?

Ok now that I have a working transaction I question my initial approach to this problem. Since I am using a CJuiButton to link to this view that I was trying to put transaction into, would it be a better approach to have the button kickoff the transaction through onclick instead? I say this because right now every time I reload the view (with transaction rolled in) a new db entry is created. Any thoughts?

Hi

Use CController.forward method, to have an id passed as argument to the view action, set the $_GET[‘id’] to the actual id

something like this




//controller

$connection = yii::app()->db;

$transaction=$connection->beginTransaction();

try 

{

        $sql1 = "INSERT INTO selection (UserId, ItemId t)

                                VALUES(".Yii::app()->user->id.",".$model->ItemId;

                

        $connection->createCommand($sql1)->execute();

        

        $transaction->commit();

}

catch(Exception $e)

{

        $transaction->rollBack();

                $this->redirect(array('view', 'id' => $model->PreviousModelId));


} 

$_GET['id']=$myID;

$this->forward('view');



Gustavo thanks for the quick response. When I add my transaction code along with your suggestion into my actionView function the view no longer displays (error 400/invalid request) and nothing occurs with my transaction (no input into db). I know I am missing the concept here.

you should log the exception to check what was the error, if any




catch(Exception $e)

{

        Yii::log($e->getMessage(),CLogger::LEVEL_ERROR);

        $transaction->rollBack();

        $this->redirect(array('view', 'id' => $model->PreviousModelId));

} 



The 400 errors probably occurs because $id, which is $GET[‘id’], is not set when redirecting to the view action, check its value before redirecting

Ok though logging I was able to uncover an error in my sql, corrected that now nothing else is logged but still page is not rendered.

I think I am missing the point of why you mention to use the forward method instead of just using


$this->render('view', array(

                        'model' => $this->loadModel($id, 'Item'),

                ));

if the transaction is successful and redirecting if it is not. But again I was unsuccessful and doing just that too, hence my original question. Unless your approach will prevent the execution of the transaction on a page reload which adds an additional row in the db.

Change of approach needed?

Ok now that I have a working transaction I question my initial approach to this problem. Since I am using a CJuiButton to link to this view that I was trying to put transaction into, would it be a better approach to have the button kickoff the transaction through onclick instead? I say this because right now every time I reload the view (with transaction rolled in) a new db entry is created. Any thoughts?

You could use just render, altho I preffer forward, because any changes you make to the view action you will have to redo it in the transaction action

To solve your next problem, you could redirect to the view, instead of forward it, or check if the transaction has already been done.