I've got a cache model that holds caches of parsed values from other tables (for the instance of the blog tutorial it might hold "contentDisplay". I am making a behavior to do this).
The model of the cache is named TextCache
It has a composite primary key:
table, id, column
The table column holds the name of the foreign table that it is caching
The id is the id of the entry in that table that it is caching
The column is the column in the entry that it is caching
So I went about setting the relations up in my User model:
<?php
public function relations() {
return array(
'textcache' => array(self::HAS_MANY, 'TextCache', 'table, id'),
);
}
But the 'ON' generated is
Quote
ON t1.`table`=`user`.`id` AND t1.`id`=`user`.`id`
How can I get it to generate:
Quote
ON t1.`table`='user' AND t1.`id`=`user`.`id`
So instead of user.id it is the name of the table? Is this possible? any suggestions?
Maybe it should be a 'condition' instead? But how would I go about getting this 'condition' injected automatically?
I think your composite relationship is not well defined because user is not a PK in your User table. You have to explicitly specify an 'on' option in your relation declaration for the 'user' column.
Not sure if the option should be 'on' or 'condition'. I'll try both after school. It was midnight last night when I wrote the above, so my mind was not working. Should have thought of this.
I'm really excited about how nicely this behavior is coming together though…
<?php
//in controller action
$A = User::model()->with('textcache')->together()->findbyPk($id);
$B = new User();
$A->parseCacheRelation(); // THROWS ERROR
$B->parseCacheRelation(); // works
//where parseCacheRelation() is supposed to be inherited from a behavior
<?php
//parseCacheRelation() is from a behavior
//in model
//throws error
public function afterFind() {
$this->parseCacheRelation();
parent::afterFind();
}
//works
public function afterFind() {
parent::afterFind();
$this->parseCacheRelation();
}
public function relations() {
return array(
'group' => array(self::BELONGS_TO, 'Group', 'group_id'),
'parsecache' => $this->parseCacheRelation(), //throws error
);
}
As for the error in relations() i'm not sure if it's another bug or by design, or I'm doing something wrong
BTW the fact that you need to call parent::afterFind() first seems a little confusing and I believe it could easily confuse others. Do you think there is any way to get around this so you don't have to?
The reason that you need to call parent implementation is similar to beforeSave/afterSave. I understand that you might not feel comfortable at first, but it is fairly standard practice and it also offers you additional flexibility.
It looks like by calling isset($this->Owner->parsecache) will actually load the data and then see if it is set. I just want to see if it is already loaded.
Is this by design, and if so, how else could I check if the related data is already loaded?
If an array element is null, isset() will return false. That's why the additional check with array_key_exists(). Because the latter is much slower than isset(), we use both here.