Monday, December 26, 2011

How to easily get all safe attributes from a Yii model

The problem
How to get all the safe attributes from a model in Yii. Let's say that we have an active record model we call product. In the productController class we have an action called updateAction(). We use a form to post data to that action. All the data comes in and we massively assign the changes to the model like this:
$productModel->attributes=$_POST['Product'];
One of the attributes in the product model is not a datatabase attribute. It is called $attr1. $attr1 is a public attribute we have added to the product model class. $attr1 is available as a text field in the form and is just a plain string. A validation rule has been added for $attr1.
We now need to loop over all the safe attributes and render them in the view using a loop.

The solution
When the data has been posted to the updateAction we send the product model in as a parameter when we render the view. Now in the view we want to loop over all the attributes and display them on screen. The natural way to do this is probably something like this:
<table>
<tr><th>Attribute name</th><th>Attribute value</th></tr>
<?php $productAttributes = $productModel->getAttributes(); ?>
<?php foreach($productAttributes as $i=>$attribute): ?>
<tr>
<td><?php echo $i; ?></td>
<td><?php echo $attribute; ?></td>
</tr>
<?php endforeach; ?>
</table>
This result in only the database connected attributes in the model being rendered. We really want all the safe attributes to be listed. Including the public attribute $attr1 we created in the product model class. This is how to do that:
<table>
<tr><th>Attribute name</th><th>Attribute value</th></tr>
<?php $productAttributes = $model->getAttributes($productModel->safeAttributeNames); ?>
<?php foreach($productAttributes as $i=>$attribute): ?>
<tr>
<td><?php echo $i; ?></td>
<td><?php echo $attribute; ?></td>
</tr>
<?php endforeach; ?>
</table>
As you can see on row 3 we are first using the read-only array of safe attributes to get all the attributes that are safe to be massively assigned. This way we get $attr1 back as well if we have added at least one validation rule to that attribute in the model. Now we use the safe attribute array to query the model instance for all the safe attributes.

In most cases you would probably explicitly add code for each attribute separately in the view. For instance when you create a form. The code above might be useful if you want to be able to add attributes to the model without having to make changes in the view.

I hope this helps somebody.

If you have a better way of doing this or spot any errors, please leave a comment.


1 comment:

  1. Anonymous2:08 pm

    Tôi là người Việt Nam, tôi chẳng biết nói gì , chỉ biết nói rằng tôi cảm ơn. Đây là tài liệu tôi đang tìm kiếm . thank you

    Hi vọng được học hỏi từ bạn
    Email của tôi
    truongton92@gmail.com

    ReplyDelete