CActiveRecord, inheritance and dynamic attributes

Hi

I have following scenario and would like to know why it is not working.

I have one class ClassA extended from CActiveRecord

class ClassA extends CActiveRecord

{

}

and I can access fields of ClassA without any issue.

$a = new ClassA;

$a->title = "Title";

I have another class which should be derived from ClassA as it has almost all fields of ClassA but some additional, now if I do following

class ClassB extends ClassA

{

}

$b = new ClassB;

$b->title = "Title";

it fails saying that ClassB doesn’t have the property

Property "ClassB.title" is not defined.

I understand CActiveREcord checks for database metadata set to find the property.

my question is.

  1. Does this mean every time we initiate a model class (derived from CActiveRecord) it fetches fields from database, or where does it keep this metadata, in which file so if we need we can modify.

  2. Is there anyway I could let CActiveRecord ClassA’s metadataset from ClassB so that in above scenario it knows all the fields of ClassA and ClassB when accessing ClassB instance

Thanks

It should work, so there’s probably a problem in some part of your code. Did you maybe implement model() again in B?

Also have a look here:

http://www.yiiframework.com/wiki/198/single-table-inheritance

http://www.yiiframework.com/forum/index.php?/topic/12978-class-table-inheritance

I’m actually not trying to do anything, just trying to assign property value

here’s my base class

class Product extends CActiveRecord

{

/**


 * Returns the static model of the specified AR class.


 * @return Product the static model class


 */


public static function model($className=__CLASS__)


{


	return parent::model($className);


}





/**


 * @return string the associated database table name


 */


public function tableName()


{


	return 'flk_product';


}

and this is Derived class

class ProductAutomobile extends Product

{

/**


 * Returns the static model of the specified AR class.


 * @return ProductAutomobile the static model class


 */


public static function model($className=__CLASS__)


{			


	return parent::model($className);


}





/**


 * @return string the associated database table name


 */


public function tableName()


{


	return 'flk_product_automobile';


}

I just trying to do this in one of my actions

$myModel = new ProductAutomobile;

$myModel->title = 1;

exception thrown at this place…

22 $myModel->title = 1;

Property "ProductAutomobile.title" is not defined.

C:\dev\projects\yii\framework\db\ar\CActiveRecord.php(145)

133 * PHP setter magic method.

134 * This method is overridden so that AR attributes can be accessed like properties.

135 * @param string $name property name

136 * @param mixed $value property value

137 */

138 public function __set($name,$value)

139 {

140 if($this->setAttribute($name,$value)===false)

141 {

142 if(isset($this->getMetaData()->relations[$name]))

143 $this->_related[$name]=$value;

144 else

145 parent::__set($name,$value);

146 }

147 }

I even tried commenting out model() in derived class but same error

So you have 2 different tables? Then it can’t work if [color="#1C2837"][size=“2”]flk_product_automobile doesn’t have a column “title”. You can’t inherit the columns from the extended AR’s table. So i guess you’re looking for a solution to class table inheritance. AFIAK there’s no good pattern for this problem yet (only for single table inheritance). Check the links i sent and also search for “inheritance” on the forum. There where some discussions about this.[/size][/color]

So you have 2 classes for two different tables…

in tableA you have the field title, but I guess that in table B you don’t have it ?

On the other hand… if you define a new property "title" in classA then you can access it in classB…

@Mike

Yes flk_product has the ‘title’ but flk_product_automobile doesn’t. and I was looking to access that property (dynamic) from derived

But my question is when debugging i can see that it look for database metadata in order to find whether property exists or not, where is this metadata stored? is it fetching from db every time? and i don’t think so.

@mdomba

Yes tableA does have and tableB doesn’t in AR classes I made ClassB extended from ClassA

so what you saying is instead of having dynamic properties I need to define those in ClassA by myself?

When you use $class->attribute… the class has that attribute defined in itself or any parent class… then this is used… if there is no defined attribute… then Yii checks the current table structure to see if in that table there is a field with that name…

For your case in classA you have that field and thats why it works… but in tableB you dont have that field and the parent class (classA) does not have that property defined… so you get the error…

Now it’s all up to you and your needs… why do you need to set this attribute in the classB when there is no field where to save this data?

If you just need that… then define that property in the classA and you will have access to it on all child classes…

@mdomba: I think he’s wants to implement class table inheritance as described here: http://www.martinfow…nheritance.html

Maybe we can come up with a solution and define another reference design pattern, just like samdark did with single table inheritance? I tried once, but my code was pretty ugly :)