I manage customer records and have a separate entity for phone numbers, since a customer record (i.e. a person) could be related to many phone numbers.
What would be the best way to handle a customer and the first three phone numbers as one entity?
For example, in the "view" view (no pun intended), I would like to display:
name: MAX LASTNAME
phone 1: 5551234
phone 2: 5556642
phone 3: not assigned
Also, in the "create" view (in _form.php), I would like to display:
phone 1: _________
phone 2: _________
phone 3: _________
What would be the best way to achieve this?
(1) can I "enrich" an ActiveRecord object with additional attributes which I add manually? Thus, I could add the first three related phone number to the model data in the CustomerController before rendering the data. The view would just access the model data, for instance with CDetailView. So nothing special on the view side.
(2) what about saving the entered phone data? How would I handle the form submit? I guess, I should update the phone number in onAfterSave() … but can I tell the ActiveRecord to ignore phone1, phone2 and phone3 for saving on the first hand, so that I can do it manually afterwards in onAfterSave()?
Of course, the simpliest solution would be just to add three columns to the "customer" table, named phone1, phone2 and phone3 - however, I think the separation into related tables would serve other needs, for example search for a phone number - would you agree on that?
Thanx for all tips,
The simplest is to add the three fields to the customer model and show them on the form. Then in the controller save the customer and if successful then save the phone numbers.
It’s not the cleanest but if you only have an additional field or two (or three in your case)… it may simplify things. What you’re really doing is displaying a form that’s not related to one specific model… so if you want to keep it clean then you should create a new form model with the combination of fields from customer and phone. Clean is good but also keep maintenance in mind… whatever works best.
I think I know what you mean. How do I add the three fields to the model [newbie question]? And in which function (event)?
I found the following two events which seem to be interesing in this case:
onAfterFind() (to populate the additional phone number fields in there?)
onAfterConstruct() (to populate empty additional phone number fields)
Just for the sake of testing, I tried in the CustomerController.php (as created by Gii):
public function loadModel($id)
/* I added the following 2 lines: */
$attributes = $model->attributes;
throw new CHttpException(404,'The requested page does not exist.');
But to no avail. In the view there was no attribute ‘phone1’. So how would I do this?
As for saving, I got your point: onAfterSave() is my friend.
But regarding the “clean” solution - I always try to keep it clean, so I’m really interested in this … Could you point me in the right direction how to use a Form Model collecting the data from 2 different models actually?
You would add the fields to the class… not to any method/function… this will make it available on the form:
class Customer extends ActiveRecord
/* Additional Fields not in the Customer table but available to class */
public static function model($className=__CLASS__)
public function tableName()
That’s how you would inject the phone numbers into the customer model. You would then access the fields like so “$this->phone1”. To merge them to a new model (the cleaner method):
class CustomerEntryForm extends CFormModel
/* Create a save function */
public function save()
/* Code to save fields to two different databases */
/* Call in controller after validation */
/* Override methods of CFormModel such as rules, attribute labels, etc. */
public function rules()
The guide is a good place to look for info:
Working with Forms
Also have a look at the "LoginForm" model which is installed with the default yii app as it uses a CFormModel.
Great! I finally understand
lgoss007, thanks a lot for clearing things up for me, I was not fully aware of how the CFormModel really worked, but now I am.