简体   繁体   中英

Working with memcache with Yii and ActiveRecords

So I've been trying to get memcache working on my site running Yii 2. I've got the caching working for the DB schema stuff, but it doesn't seem to work for ActiveRecord queries.

This is my config for the DB:

'db' => [
    'class'                 => 'yii\db\Connection',
    'dsn'                   => 'mysql:host=127.0.0.1;dbname=db_name',
    'username'              => 'user_name',
    'password'              => 'password',
    'charset'               => 'utf8',
    'enableQueryCache'      => true,
    'queryCache'            => 'cache',
    'queryCacheDuration'    => 600,
    'enableSchemaCache'     => true,
    'schemaCache'           => 'cache',
    'schemaCacheDuration'   => 3600,
]

According to the guide ( http://www.yiiframework.com/doc-2.0/guide-caching-data.htm ), this should be enough to get global caching working. From my understanding, if those variables are set, then it should cache all queries for the time specified, or do I still have to specifically call if with the following?

$result = Customer::getDb()->cache(function ($db) {
    return Customer::find()->where(['id' => 1])->one();
});

I went digging into the code base to see what is going on and it looks like in \\yii\\db\\Connection::getQueryCacheInfo() was changed to start like the following: it would work perfectly:

public function getQueryCacheInfo($duration, $dependency)
{

    if (!$this->enableQueryCache) {
        return null;
    }

    $duration = (isset($duration)) ? $duration : $this->queryCacheDuration;
    $dependency = (isset($dependency)) ? $dependency : $this->queryCache;

Am I doing something wrong here? Why can't I get memcache to be used by default for all queries?

Thanks

If you really want caching "for all queries" you would be better of enabling the query cache of your database. It is much better at that. Besides the database schema there is no caching going on unless you explicitly enable it, like in your example.

The documentation for $enableQueryCache clearly states it:

Whether to enable query caching. Note that in order to enable query caching, a valid cache component as specified by $queryCache must be enabled and $enableQueryCache must be set true. Also, only the results of the queries enclosed within cache() will be cached.

If you really wanted to do it there is a way to hack it in but IMO it's not worth it:
Create your own ActiveQuery derived class. In its createCommand() method already enable caching before returning the command object:

class MyActiveQuery extends ActiveQuery 
{
   public function createCommand($db = null)
   {
      $command = parent::createCommand(db);
      $command->cache();
      return $command;
   }
}

Then you'd have to override the find() -method of every ActiveRecord class you wish to have cached to return one of your ActiveQuery instances instead.

public static function find()
{
    return Yii::createObject(MyActiveQuery::className(), [get_called_class()]);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM