Difference between #3 and #4 of
ISA hierarchy of tables inside a database and how to implement a single form

Revision #4 has been created by pligor 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
The
refore 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 the role for both attrB and attrC
 
I also edited the "rules" method of 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.
 
I created 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 controller
 
 
So currently I use the controller to call explicitly $modelB->save() or $modelC->save().
 
There was 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.
 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 dropdown list feeds the "categ" attribute
 
 
This way the used has chosen the class.
 
So 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 a textbox 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
 
 
But currently I use the controller to call explicitly $modelB->save() or $modelC->save()
 
There is 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
1 0
3 followers
Viewed: 17 877 times
Version: 1.1
Category: How-tos
Written by: pligor pligor
Last updated by: pligor pligor
Created on: Jun 27, 2011
Last updated: 14 years ago
Update Article

Revisions

View all history