Take this piece of code as an example:
public function actionPostOneWay( $postId )
{
$dependency = new CDbCacheDependency( 'SELECT publish_date FROM posts WHERE id = :post_id;' );
$dependency->params = array( 'post_id'=>$postId );
$post = Post::model()->cache( 59, $dependency )->findByPk( $postId );
// process post one way
}
public function actionPostAnotherWay( $postId )
{
$dependency = new CDbCacheDependency( 'SELECT publish_date FROM posts WHERE id = :post_id;' );
$dependency->params = array( 'post_id'=>$postId );
$post = Post::model()->cache( 59, $dependency )->findByPk( $postId );
// process post another way
}
So will accessing /postOneWay
and /postAnotherWay
reuse the same cached object, or will they create cache objects of their own?
I tried to cache the same query in two different actions and yes, the same cached object will be used. One can see that enabling CProfileLogRoute
in application's configuration file.
Looking at the source code of CActiveRecord
class I stated that public function findByPk($pk,$condition='',$params=array())
method (and other query methods) use protected function query($criteria,$all=false)
. This one, in turn, finally relies on private function queryInternal($method,$mode,$params=array())
of CDbCommand
class where Yii makes its caching work with database queries.
As one can see a cache key used to store and restore queries' results is defined as follows:
$cacheKey='yii:dbquery'.$this->_connection->connectionString.':'.$this->_connection->username;
$cacheKey.=':'.$this->getText().':'.serialize(array_merge($this->_paramLog,$params));
if(($result=$cache->get($cacheKey))!==false)
{
Yii::trace('Query result found in cache','system.db.CDbCommand');
return $result;
}
This key doesn't take a cache dependency instance into consideration. CDbCacheDependency
is only used to determine whether something is changed in database and new query is to be executed to update the cache. To say more - if you specify different SQLs to create CDbCacheDependency
in two actions only one of them (executed first) will make sense during caching time due to the instance of CDbCacheDependency
is cached serialized along with query's result:
if(isset($cache,$cacheKey))
$cache->set($cacheKey, $result, $this->_connection->queryCachingDuration, $this->_connection->queryCachingDependency);
Caching an instance of evaluated dependency could be seen in public function set($id,$value,$expire=0,$dependency=null)
method of CCache
class:
if ($dependency !== null && $this->serializer !== false)
$dependency->evaluateDependency();
if ($this->serializer === null)
$value = serialize(array($value,$dependency));
elseif ($this->serializer !== false)
$value = call_user_func($this->serializer[0], array($value,$dependency));