Problem with transaction

I want to add one payment and several products in my DB. And i want to protect adding by transaction.

I use InnoDB tables.




$transaction=Yii::app()->db->beginTransaction();

try 

{                          

	$payment=new Payment;

	$payment->amount=10.00;

            

	$payment->save();

                    

	foreach($products as $k=>$v)

	{

		for($i=1;$i<=$v;$i++)

		{

			Yii::log('Start adding of product '.$k.'-'.$i, 'info', 'modules.admin.products');

			$product=new Product;                    


			$product->user_id=1;

			$product->payment_id=$payment->id;

			$product->product_id=$k;

			//

			//Info is required!!!

			//Transaction should be failed!!!

			//

			//$product->info='some text';

							

			Yii::log('Start saving of product '.$k.'-'.$i, 'info', 'modules.manage.usersController');                                    

			if(!$product->save())

			{

				Yii::log('Can\'t save product: '.print_r($product->getErrors(), true), 'error', 'modules.admin.products');    

			}

		}

	}

	$transaction->commit();

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

}

catch (Exception $e)

{

	$transaction->rollBack();

	Yii::log('Transaction error: '.print_r($e->getMessage(), true), 'error', 'modules.admin.product');

	$model->addError('payment', 'Database transaction failed.');

} 



info variable of $product model is required. So transaction should be failed.

But what i have in logs




2012/08/18 16:48:34 [trace] [system.db.CDbConnection] Starting transaction

2012/08/18 16:48:34 [trace] [system.db.ar.CActiveRecord] Payment.insert()

2012/08/18 16:48:34 [trace] [system.db.CDbCommand] Executing SQL: INSERT INTO some query here

2012/08/18 16:48:34 [info] [modules.admin.product] Start adding of product 424103-1

2012/08/18 16:48:34 [info] [modules.admin.product] Start saving of product 424103-1

2012/08/18 16:48:34 [error] [modules.admin.product] Can't save userLicense: Array

(

    [info] => Array

        (

            [0] => Info cannot be blank.

        )


)

2012/08/18 16:48:34 [trace] [system.db.CDbTransaction] Committing transaction



So product model wasn’t saved because of error, but transaction was commited! And I have payment record in my DB without any product!!!!

Why?

The problem is that you do not throw(!) the exception

try something like this




if(!$payment->save()) 

 throw new Exception($error);

...

			if(!$product->save())

			{

				Yii::log('Can\'t save product: '.print_r($product->getErrors(), true), 'error', 'modules.admin.products');

                                throw new Exception($error);    

			}



Then the rollback should work.

Yes I thought about it but manual http://www.yiiframework.com/doc/api/1.1/CDbTransaction says nothing about throwing of exceptions! So is it necessary?

The example snippet in quoted API page does not use AR.

I think in your case (using AR with save() method) yes.