Does Massive Assignment Work On Class Variables?

Hi guys - a noob here, so I apologize if this is an elementary questions, but I was unable to find an answer through searching. I have a form that gets both db attributes and class variables. This code works fine - it assigns both my attributes and variables:

$model->attributes = $_POST['Billing'];

However, I need a second instance of the model because I am writing two rows to the db, so I do this:

$model2 = new Billing;

$model2->attributes = $model->attributes;

The db attributes copy to the second instance just fine, but none of the class variables copy over (and I do have a safe rule for them). I have quite a number of class variables, so I was hoping I wouldn’t have to do individual assignments for each. Why does the massive assignment work with the _POST data, but not with the model-to-model assignment? Is there an alternative way to do a model-to-model assign that would include class variables?

I’d appreciate any insight anyone might have into this.


Assuming you’re performing this second insertion at the same time as the first, could you not just assign both from the POST data?

$model->attributes = $_POST['Billing'];

$model2->attributes = $_POST['Billing'];

Thanks Keith - that works. There are several fields I fill after the POST data assignment, so with the new instance I’ll have to manually assign those as well - would have been nice to be able to do it in one massive assign, but no big deal. Any idea why POST-to-model massive assignment includes class variables, but model-to-model massive assignment does not? Is it supposed to work that way, or is that a bug?

Out of interest, what’s the purpose of the fields that you’re manually assigning?

Regarding your question, I’m not sure what the reasoning is if Yii does behave that way. I thought I’d done such assignments before without any problem, but I may well be misremembering. I may have a look at my own code tomorrow, as well as the Yii source.

Yii will assign massively all attributes that are safe, it means all attribute with a validator defined on them.

If you assign manually some attributes you probably don’t have any validator on this properties, and that’s right because they are not supposed to be assigned according to user input.

Just assign manually to both models.

I’ve also noticed inconsistencies between CFormModel::getAttributes/setAttributes an CActiveRecord::getAttributes/setAttributes. I think, they all should read and write class properties (and even properties defined with getter/setter).

We should open a ticket for this - just don’t have time right now.

Keith - the code in question relates to a billing process, so much of the data submitted via the form (i.e. credit card data) I am not saving to database. However, based on choices made by the user on the form, there are variables that I manually set that are used to build xml strings (which represent the credit card requests) that are posted to the credit card processors gateway via cURL.

Zaccaria - thanks for the insight. I thought my rules were set up properly, but maybe I missed something, or there’s a problem in my scenarios. I will double check and do some additional testing.

@jkats: $model2->attributes = $model->attributes is equivalient to $model2->setAttributes( $model->getAttributes() ); The problem is, that for active records, getAttributes does not return custom class properties or properties defined through a setter. That’s what i tried to say above :)

A-ha, makes sense now - good information to know! Thanks Mike!