Dynamic Relations For Model [Solved]

I want my relations() function work like that:





/**

* ...

* ...

* @property $block_type

* ...

* ...

*/


class Block extends CActiveRecord

{	


...


    public function relations()

    {

        return array(

	    'images'=>array(self::HAS_MANY, 'Images'.ucfirst($this->blockTypeName), 'block_id'),

	            );

    }


...


}



$this->blockTypeName is a virtual property:




protected function getblockTypeName(){			

    $res = BlockTypes::model()->findByPk($this->block_type);

    return $res->type_name;

}



I have another table with blockTypes Id’s and their names and want to use different tables in my relations depending on my blockType property.

The problem is that I can not access $this->block_type (which is a normal property, not a virtual one) like that.

Perfectly works outside class, but not inside.

I can not access any property inside relations().




Property "Block.id" is not defined.



I know I’m wrong in my assumptions about $this scope, but can not understand where.

Any ideas?

Hi anvar.t,

As you may notice, we can think of 2 different kinds of objects for a CActiveRecord.




$models = MyModel::model()->findAll($someCriteria);



In the above, “MyModel::model()” will create a pseudo static object that provides various functions to perform database query. It is an instance of MyModel class, but it doesn’t contain a particular data of a database record. We use it to get the data from the database … this is the 1st one.

And findAll function returns an array of MyModel objects into $models. They are also the instances of MyModel class and each of them represents a concrete data in a database record … they are of the 2nd kind.

Now, you seem to try to apply the “relations” method to the 2nd kind of AR objects. But the search criteria which defines the relation is for the 1st kind which doesn’t have a data for the block type. I think that’s the reason why your attempt fails.

Thank you for reply, Softark!

But the problem i think one step higher then it looks.

Even if I had my $this->block_type not as a link to another table, but something like that (without virtual getter):




/**

* ...

* ...

* @property string $block_type <---------------now it is not an ID, just string

* ...

* ...

*/




class Block extends CActiveRecord

{       


...


    public function relations()

    {

        return array(

            'images'=>array(self::HAS_MANY, 

            'Images'.ucfirst($this->blockTypeName), // <-- trying to get real property here

            'block_id'),

                    );

    }


...


}



I know that there’s a blank area in my knowledge about PHP OOP… That’s why




 public function relations()

    {

        print_r($this); exit;


        return array();

    }   



Gives me a blank object…

I have not dug deep inside CActiveRecord, but it looks like when relations() is invoked, there’s nothing in object.

So after a glass of vermouth I solved it by virtual getter:




protected function getimages(){

	$imageModelName = 'Images'.ucfirst($this->blockTypeName);


	$c = new CDbCriteria();

	$c->addCondition("block_id=:id");

	$c->params = array(':id'=>$this->id);

	$images = $imageModelName::model()->findAll($c);

		

	return $images;

}



And removed everything from relations().

But what I wanted to implement I’d name “recursive relations” which is not possible now in current version of YII. That would be more flawless then my solution.