views:

182

answers:

2

Hi everyone,

I am having some second thoughts about where to implement the caching part. Where is the most appropriate place to implement it, you think?

Inside every model, or in the controller?

Approach 1 (psuedo-code):

// mycontroller.php

MyController extends Controller_class {
   function index () {
        $data = $this->model->getData();
        echo $data;
   }
}

// myModel.php

MyModel extends Model_Class{
    function getData() {

        $data = memcached->get('data');

        if (!$data) {
            $query->SQL_QUERY("Do query!");
        }

        return $data;
    }  
}

Approach 2:

// mycontroller.php

MyController extends Controller_class {
   function index () {
        $dataArray = $this->memcached->getMulti('data','data2');

        foreach ($dataArray as $key) {
            if (!$key) {
                $data = $this->model->getData();
                $this->memcached->set($key, $data);
            }
        }

        echo $data;
   }
}

// myModel.php

MyModel extends Model_Class{
    function getData() {           
        $query->SQL_QUERY("Do query!");

        return $data;
    }  
}

Thoughts:

Approach 1:

  • No multiget/multi-set. If a high number of keys would be returned, overhead would be caused.

  • Easier to maintain, all database/cache handling is in each model

Approach 2:

  • Better performancewise - multiset/multiget is used

  • More code required

  • Harder to maintain

Tell me what you think!

+3  A: 

Caching should be done in the model. If I had to choose in general, I would probably end up transparently caching the model's database interaction, which wouldn't require you to make any changes to the rest of your code. This of course would be done in the parent class of your models.

Definitely focus on caching your database query results, as interfacing with your database is where you will see the most overhead. I would argue that it would be more efficient to cache your database results (or maybe your entire initialized model) more than anything else.

Remember that you can serialize your objects before caching, so sending complex types (arrays or objects) into memcache shouldn't be a problem. PHP 5 provides the magic methods __sleep() and __wakeup() for the very purposes of seralizing and reconstructing your serialized objects. Caching full objects in PHP is basically a piece of cake. See http://php.net/manual/en/language.oop5.magic.php for more info.

Whether you decide to cache just your data or your entire model shortly after initialization is up to you.

Kenaniah
That is a very interesting idea, doing it in the parent of the model seems like a really good idea! Will definitely look out of my box to do such!
Industrial
+6  A: 

I would keep my caching responsibilities firmly within the model. It is none of the controller's or view's business where the model is getting data. All they care about is that when data is requested, data is provided - this is how the MVC paradigm is supposed to work.

Abstract your mem_cache functionality into the parent model class. It will cut down on the amount of code you need to write (code = time = money), simplify modifications to the system, and eliminate the number of bugs you produce per model that you build (see previous formula).

Standardize, standardize.

Jarrod
Thank you for the good answer. I'm just wondering, how does one actual implement caching in the model? Do you save the data with the SQL query itself as the key? What about if you're using prepared statements? There would be a key conflict for different parameters. If you're not using the query itself, how do you uniquely identify a result set? If the answer is too complex I'll make a separate question for this.
Lotus Notes
I would suggest using the md5 hash of your query combined with a serialized version of your input arguments.
Kenaniah
That definitely does not seem efficient. If the programmer can't directly choose when to cache and when to not cache, then how can the Model itself differentiate between searches and regular SELECT queries for simple display? This in itself seems almost like an argument to cache in the Controller, since one of the main rules of caching is that you should not cache unless necessary, and in most cases you shouldn't cache search results unless you're Google. Why not just tell it when to cache in my controller, where I would have full control?
Lotus Notes
This discussion is worthy of its own question - the original question concerned MVC implementation. This is a question more specific to results caching.
Jarrod
Allright. Started a new question here: http://stackoverflow.com/questions/2916645/implementing-model-level-caching
Lotus Notes