Model caching.

Hello, I have one issue with caching.

If I run something like this:




$model = new Article();

$articles = $model->cache(100)->byCategory(Category::model()->findByPk(1))->findAll();



Actually will be cached Category model, not Article. Because cache() method only tells CDbConnection, to cache next request.

P.S. I know, this is not the cleanest example, but it is very simple to understand, what is wrong.

Caching should be applied only before actual find. I did some hack for this:




protected $_cacheOptions;


public function cache($duration, $dependency=null, $queryCount=1)

{

  $this->_cacheOptions = array(

    'duration' => $duration,

    'dependency' => $dependency,

    'queryCount' => $queryCount,

  );




  return $this;

}


public function applyScopes(&$criteria)

{

  parent::applyScopes($criteria);


  // Adds caching after all scopes

  if($this->_cacheOptions) {

    parent::cache($this->_cacheOptions['duration'], $this->_cacheOptions['dependency'],

      $this->_cacheOptions['queryCount']);

  }

}



Somebody will ask why I moved this to applyScopes, instead of beforeFind(). This is because beforeFind is executed before applyScopes, what is actually wrong too.

This will be really nice, if it can be fixed in 1.1.11 release. Because this is very dirty hack. Because, when I tell to cache article model, I want to cache it exactly, not next request.

I have spend long time yesterday in very similar situation understanding why did my model does not caches.

BUG #2 Params binding and caching

When you dynamically bind parameters (for example: findAllByAttributes).

You get binded keys something like this: ycp0, ycp1, ycp2.

You can have queries with params:

Query1: ycp0, ycp1

Query2: ycp2, ycp3

But if you will call additional query between this two queries, you will get something like this:

Query1: ycp0, ycp1

QueryAdditional: ycp2, ycp3

Query2: ycp4, ycp5

Caching key is generated by SQL statement, and in situation #2 caching for Query2 will not be found and will be generated new instead of using existing.

Updated:

Same for identical requests, if you will call twice same query, you will get different bind params.

2587

binding.jpg

Any way to fix it while keeping backwards compatibility?

The same issue is here. Actual have big problem with query caching.

Question about #1 or #2 issue?

About #2 issue.

If we can make params to be unique inside one query (including relations + relational scopes), I don’t see any problem there.

Bug is really bad, when you will use caching for multiple models. If one of the caching duration will end and it will be executed, all next queries will have different params and caching will break. Next queries will run and cache again, with different parameters.

The problem is that:

  1. We’re forming criteria before using it.

  2. At the time we’re forming criteria we don’t know if it will be used in relational query or in multiple queries.

If you have a solution to this, feel free to make a pull request at github and we’ll review it. If not, descibing your issue there with code samples will help as well.