How To Instantiate A Relation's Active Record (Single Table Inheritance)"?

Title explains it all. Here is the source:


//Class ObjectData

public $id;

public $object_id;

public $handler_class_name;


protected function instantiate($attributes){

	if(!isset($this->handler_class_name))

		$class = get_class($this);

	else

		$class = $this->handler_class_name;


	$model=new $class(null);

	return $model;

}


public function relations() {

	return [

		'data'=>[self::BELONGS_TO, 'Object', 'object_id']	

	]

}


//class Object

public $id;

public $name;


public function relations() {

	return [

		'object'=>[self::HAS_MANY, 'ObjectData', 'object_id']	

	];

}


public function defaultScope() {

	return ['with'=>['data']];

}


public function search() {

	$criteria = new CDbCriteria;

	$criteria->compare('id', $this->id);

	$criteria->compare('name', $this->name, true);

	return new CActiveDataProvider($this, ['criteria'=>$criteria]));

}

Test Code:


foreach($model->search()->getData() as $objects) {

	foreach($objects->data as $data) {

		echo get_class($data).'<br>';	

	}	

}

Test Rows


objects

1 "Test1"

2 "Test2"


objects_data

1 1 "Test1ContentData"

1 2 "Test1FileData"


2 1 "Test2RawData"

2 2 "Test2ScriptData"

2 3 "Test2FileData"



Test Results:


ObjectData //(5 times)

Expected Results:




Test1ContentData

Test1FileData

Test2RawData

Test2ScriptData

Test2FileData




instantiate is called BEFORE attributes are set (it is supposed to create object instace which attributes has to be set), so:


if(!isset($this->handler_class_name))

is wrong. it should be:




protected function instantiate($attributes){

        if(!isset($attributes['handler_class_name']))

                $class = get_class($this);

        else

                $class = $attributes['handler_class_name'];


        $model=new $class(null);

        return $model;

}



Do not forget about


$model->isNewRecord = $this->isNewRecord;

unless you wanna be obsessed with unusual bugs.