Storing Fetched Active Records In One Pool

Sometimes there is a number of models with same primary keys used in different places, widgets, modules. We always have to get them from DB even if we already did this and sometimes there are too much redudant queries. Just a simple thought, what if we will have a pool of fetched AR instances, then if we need to find some, we will search this pool first and query DB only if we didn’t find it.

I basically implemented such class. It uses common pool in ARPool class for all children classes (another option is to have such pool property in every child class, but I like this option because it’s more centralized and you don’t need to change your final classes at all). This is the key part:




class ARPool extends CActiveRecord

{

    private static $_pool = array();


    public static function registerRecord(ARPool $record)

    {

        $class = get_class($record);

        $pkAttr = $record->getMetaData()->tableSchema->primaryKey;


        if (!isset(self::$_pool[$class]))

            self::$_pool[$class] = array();


        self::$_pool[$class][$record->$pkAttr] = $record;

    }


    /* There are overridden CActiveRecord methods: populateRecord(), findByPk(), etc. */


}



All you need is to change "class Comment extends CActiveRecord" to "class Comment extends ARPool" and it works the same way.

This also have a side effect I consider positive: every model is always the same object, no matter where it was raised.




$c1 = Comment::model()->findByPk(135);

$c2 = Comment::model()->findByPk(135);


echo $c1->content; // prints "Old value"

$c1->content = "New value";

echo $c2->content // prints "New value"



This idea is not somethig big, of course, but I never saw this working with Active Record before. I assume there may be some pitfalls I don’t see. Critique and comments are welcome.

Also I can place it to github if anyone is interested.

Hi Thaumant, welcome to the forum. :)

We already have a convenient "query caching" functionality in Yii.

http://www.yiiframework.com/doc/guide/1.1/en/caching.data#query-caching

You should note that a life cycle of PHP program is very short. It starts with a single http request and it ends when the response has been sent. All the cache entries that you have stored in PHP variables will be lost when a page has been rendered. For the next page, you have to start from the scratch, gathering the AR objects from db.

Hi, thanks for response. I also was interested in speed and memory use because my app fetches hundreds of records with crossing primary keys.

I made simple test and it looks nice (ordinary model with 8 fields, same pk, framework caching off, remote DB):

Memory consumption is fine and the last result will be better with caching. This removes all questions. Thanks again.

I’m sorry but I don’t believe that your scenario has a good chance to be applicable in the real world apps.

Would you please explain your app a little more? Why does it have to fetch so many instances of the same record?

Crossing, not the same. Just intensive work with overlapping trees.

Crossing primary keys? What does it mean? I’ve never heard of the term.

But, yes, I guess retrieving a complicated tree should require a lot of queries and could be very slow with an ordinary methods.

I’d like to see how your ARPool works to accelerate the real app. :)

Crossing is not term, it’s just my bad English :) Word ‘intersection’ might be better.

And I just abandoned this class: extra complexity doesn’t worth removed overhead, that is not so big as I expected.