Revision #4 has been created by pligor on Aug 2, 2011, 8:33:41 AM with the memo:
this wiki is much more concrete now
« previous (#3)
Changes
Title
unchanged
ISA hierarchy of tables inside a database and how to implement a single form
Category
unchanged
How-tos
Yii version
unchanged
Tags
unchanged
ISA, hierarchy, modelling
Content
changed
[...]
Remember the parent class (created from gii) has already access to its children from the public function relations. So exploit this to get the child object.
Note: that this solution works only if row of A has ONLY ONE child, either B or C
The goal is to create a common form to fill the database tables a and b or c
So you need an attribute to differentiate the category. Is model A a parent of B or a parent of C? Once more you use custom properties. I used getCateg and setCateg methods. In my case if model A is a newRecord then the category is **null** but you may want to use a different solutionapproach
//...[...]
-I create with the help of CHtml a drop down list so user can select B or C
This drop down list has values (0, 1) which correspond to class B or C
Therefore I have added to class A an array which remembers this correspondace from value => class
The textfield of the dropdown list is taken from an explanation function inside class B and class C
So ok the user has chosen the class. Now I would like to have a textbox to fill the attrB and attrC in a COMMON way.
I use the "activeForm" widget so I would like to keep all the functionality
Of course if I use a textbox for the model B I would have to add a SECOND textbox for the model C
Above solution is not at all intuitive for the user. We would not like to have two textboxes but a SINGLE textbox.
I added an attribute named let's say "attr" inside class A to play extra bonus is that this "categ" custom property is an attribute that can be used from the form widget and be validated
```php
$attribute = "pvCat";
print $form->labelEx($model, $attribute);
print $form->dropDownList( $model, $attribute, $model::getCatDescs() );
print $form->error($model, $attribute);
```
As you see you have a seamless portion of code as the rest of the attributes which are real columns in table "a"
So the
dro
le for both attrB and attrC
I also edited the "rules" method ofpdown list feeds the "categ" attribute
This way the used has chosen the class
A.
Now I could create a textbox based on model A.
When the user submits the form the controller distinguishes from the dropdown list whether we deal with B and C.
ISo you can now add a $protocol variable in your class A.
This protocol is only temporary and plays the same role for both class B and C.
This way you create
d a
protected attribute to remember the choice of B or C
In that effect I created a new public method for class A where I could set this protected attribute and not only:
I use the relations to instantiate a new model B or C (for example $modelA->modelB = new modelB;)
I set the primary key of the model B (or C) according to the primary key of model A
and return the model B (or C) for further processing by the controllertextbox to fill protocol for either class B or class C in a seamless way.
```php
$attribute = "protocol";
print $form->labelEx($model, $attribute);
print $form->textField($model, $attribute);
print $form->error($model, $attribute);
```
I also edited the "rules" method of class A. For instance the "categ" has the 'in' validator with a specific range
SoBut currently I use the controller to call explicitly $modelB->save() or $modelC->save()
.
There
wais an idea to override save() function in class A to automagically save the
child model (since in object oriented terms the class/model A is an abstract class)
Please let me know if that works better for you
.