[EXTENSION] CSaveRelationsBehavior

I’m not really sure what you mean with the ‘flipped key definition’. Correct me if I’m wrong, but I thought Yii’s MANY_MANY relations are supposed to work like this:

	public function relations() {

                return array(

                        'relation' => array(self::MANY_MANY, 'OtherModel', 'JoinTable(MY_PRIMARY_KEY, RELATED_PRIMARY_KEY)'),



That’s the way I set it up, and that’s the only way I get a proper result set back from Yii. As I said, if I change the key definition in the relation definition, it doesn’t change the CDbException that gets thrown when I call the save() method on my model…

To clarify things a bit more, what is the exact exception you get in that case? Is it the same?

Yeah, it’s the same Exception wether I flip the keys or not:

Hmm… To me, it makes no sense that it triggers the same error in both cases.

Anyway, while testing with no foreign keys set on the MANY_MANY table, I ran into an error while saving the data.

I’m writing some fixes about that and come back to you as soon as it’s working fine.

Thank you for you help.


I’ve installed the demo application 11. Everithing works fine except when I try to update a library I get this error:“Property “LibraryBook.” is not defined.”

Help me please.


I have a problem with a MANY_MANY relation, where my relation table looks like this:

CREATE TABLE `CategoryRelation` (

  `idCategory` int(10) unsigned NOT NULL,

  `idCategoryRelation` int(10) unsigned NOT NULL,

  PRIMARY KEY  (`idCategory`,`idCategoryRelation`),

  KEY `idCategoryRelation` (`idCategoryRelation`),

  CONSTRAINT `CategoryRelation_ibfk_1` FOREIGN KEY (`idCategory`) REFERENCES `Category` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,

  CONSTRAINT `CategoryRelation_ibfk_2` FOREIGN KEY (`idCategoryRelation`) REFERENCES `Category` (`id`) ON DELETE CASCADE ON UPDATE CASCADE


the relation defined in my "Category" class looks like this:

'arrCategoryRelation' => array(self::MANY_MANY, 'Category', 'CategoryRelation(idCategory, idCategoryRelation)'),

the problem is that the only relations that would be save, are the one where the ids are identically, i.e.:




but not:







any suggestions?

Hi All,

Warmest Regards.

I try to run the demo10, i getting error

CExceptionDescription Property "LibraryBook.0" is not defined.

Source File C:\inetpub\wwwroot\yii\framework\db\ar\CActiveRecord.php(126)

Could any one let me know what is going wrong. I’m using MSSQL Database.

Thank you.



Hi all,

I’m trying demo11 and I get this error when I try to add a book.

I’m using yii 1.1.4


Hi all,

I’ve been very busy lately and I wish you forgive me to give no answer to your previous messages.

Seems like the demos applications are buggy, specially the Yii 1.1 one.

I will try to fix that as soon as possible and publish a corrected version.

Thanks for you patience and support.



Merci Juban de penser à nous!

Thank you for thinking of us

I have a table "service" which has multiple "transactions" associated to it - I have this part working well. It gets complicated because each transaction has a cost associated with it, and I want the cost of all the transactions to be shown in a separate field when I look at the "service" record.

I can sort of get this to work, but it only happens when I press save twice - so what I think is happening is that the transaction records are being created after the service record has been created/saved (thus not loading my custom behavior to calculate the total cost of all transactions).

Is there a better way I should be trying to achieve my outcome?


Could you give me the relations array you declared in you model please?

I’m nit sure I get your explanations right.


Sure thing! In my model Service.php…

    public function behaviors()


        return array(

             'CSaveRelationsBehavior' => array(

                'class' => 'application.components.CSaveRelationsBehavior',


                'relations' => array(

                        'stockTrans'=>array("message"=>"Please, check the Stock Items"),



            'ServiceBehavior' =>'application.modules.service.components.ServiceBehavior',



public function relations()


	return array(

                    'stockTrans' => array(self::HAS_MANY, 'StockTrans', 'sr_id'),



and in my Service view controller…

public function actionView($id)






                    $model->setRelationRecords('stockTrans',is_array(@$_POST['StockTrans']) ? $_POST['StockTrans'] : array());

                    if(isset($_POST['addStockTrans'])) { $model->addStockTrans(); }

                    if(isset($_POST['deleteStockTrans'])) $model->deleteStockTrans($_POST['idx']);

		if($model->save()) {






So the Service model calls a behavior that does some calculations to determine the total cost of all the "total" columns in the StockTrans model (via an afterSave). This behavior is not being called after the execution of the StockTrans. Well it kind of is, but it requires two saves to actually "see" the value of the total of the related "StockTrans" records as from what I can gather it is being executed after the save of the first Service record?

I’m starting to get it :)

It would be helpfull if you could provide the ServiceBehavior code to see what could go wrong.

I’m not too sure about the order in which the different behaviors get called. Perhaps, it’s a related issue.



ServiceBehavior file attached :)


After a quick look to your code, I think you should inactivate the transactional mode of the SaveRelationsBehavior ($transactional property must be set to false). Can you try that and let me know?




I am using CSaveRelationsBehavior (Latest version available) extension but getting this error

"An error occured during the save of contactPhones"

for the corresponding relation.

Please any help will be highly appreciation.

My Controller

public function actionCreate()


	$model=new Contacts;             







		// Set relations attributs values

		$model->setRelationRecords('contactPhones',is_array(@$_POST['ContactPhones']) ? $_POST['ContactPhones'] : array());

		$model->setRelationRecords('contactEmails',is_array(@$_POST['ContactEmails']) ? $_POST['ContactEmails'] : array());

		$model->setRelationRecords('contactWebsites',is_array(@$_POST['ContactWebsites']) ? $_POST['ContactWebsites'] : array());











My Model

public function addPhone() {

	$this->addRelatedRecord('contactPhones',new ContactPhones,true);


public function addWebsite() {

	$this->addRelatedRecord('contactWebsites',new ContactWebsites,true);


    public function addEmail() {

	$this->addRelatedRecord('contactEmails',new ContactEmails,true);


Thanks in advance


First thing to ckeck is that there are no ‘required’ rules in your relation model applying to the foreign key to your Contact model.

If you generated the model with gii, it will be the case by default, so you should remove the rule by hand.

Please, let me know if this is working now.



Hi Alban,

I’ve just revisited this code (I put up with the “press twice” bug for a while now! :) I’ve re-written some of my code and this issue that I reported above still exists.

In summary:

  • I use this CSaveRelationsBehavior to set the line items to a Request record.

  • I would like to populate the SUM of the line items on the Request record.

  • For this to occur it only sets the correct SUM on the 2nd save of the record.

I have worked out (I think?:) that this happens because Request record is being saved prior to the line items/related records, thus when the SUM is performed the old value is displayed.

I have tried using both true and false for transactional mode, but I see no difference.

I am attempting to perform the following calculation on the beforeSave() of the Request.

$query = Yii::app()->db->createCommand()->select(‘SUM(total) as SUM’)->from(ServiceRequestStockTrans::model()->tableName())->where(“sr_id=:sr_id”, array(‘sr_id’=>$this->id))->queryRow();

So I know it’s all about the timing and when the variables are set, and it makes sense why it occours… But I am not sure about the best approach to solve it? Do you have any suggestions? :)



Obviously, the SUM calculation should be performed at the very end of the process. So, it makes sense that it doesn’t work in the beforeSave Event.

Looking at your ServiceBehavior, I was wondering if you tried to make it a subclass of the CSaveRelationsBehavior instead of CActiveRecordBehavior?

Another thing to try is to call the refresh() method of your main ActiveRecord before making the sum computation to be sure you have it uptodate.