Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How ActiveRecord does support cache #7399

Closed
raminious opened this issue Feb 23, 2015 · 4 comments
Closed

How ActiveRecord does support cache #7399

raminious opened this issue Feb 23, 2015 · 4 comments
Labels
type:docs Documentation
Milestone

Comments

@raminious
Copy link
Contributor

Before I open this issue, I searched for hours in Github, Google and Yii forums

As explained in Yii2 documentations there are a way to cache queries using $db instance.

$result = $db->cache(function ($db) {

    // the result of the SQL query will be served from the cache
    // if query caching is enabled and the query result is found in the cache
    return $db->createCommand('SELECT * FROM customer WHERE id=1')->queryOne();

});

But because I don't like write SQL code in ActiveRecord, how should implement query cache feature with ActiveRecord ?

Such as yii1 way:

$customer = new Customer();

$cacheDependency = new yii\caching\DbDependency('SELECT MAX(...) FROM customer');

$custome->find()
    ->where(['id' => 1])
    ->cache(3600, $cacheDependency)
    ...
    ->one();

I searched about this issue and traced ActiveRecord where found I should override in yii\db\Query and change one() and all() methods.

For example current one() method in yii\db\Query is:

public function one($db = null)
    {
        return $this->createCommand($db)->queryOne();
    }

And must to be change to:

yii\base\ActiveQuery :

public function cache($duration = 0, $dependency = null)
{
    $this->cacheDuration = $duration;
    $this->cacheDependency = $dependency;
}

public function one($db = null)
{
    $row = parent::one($db, $this->cacheDuration > 0);
    if ($row !== false) {
        $models = $this->populate([$row]);
        return reset($models) ?: null;
    } else {
        return null;
    }
}

For yii\base\Query :

public function one($db = null, $shouldCache = false)
{
    if ($db === null)
        $db = Yii::$app->getDb();

    if ($shouldCache == true){
        return $db->cache(function ($db) {
            return $this->createCommand($db)->queryOne();
        }, $this->cacheDuration, $this->cacheDependency);
    } else {
        return $this->createCommand($db)->queryOne();
    }
}

Note: I didn't tested above codes

Am I in right way or there is cleaner solution to implement cache in ActiveRecords ?

@samdark samdark added the type:docs Documentation label Feb 23, 2015
@samdark
Copy link
Member

samdark commented Feb 23, 2015

$result = Post::getDb()->cache(function ($db) {
    return Post::find()->one();
});

Indeed docs aren't clear about it.

@raminious
Copy link
Contributor Author

@samdark thank you

@cebe cebe added this to the 2.0.3 milestone Feb 23, 2015
@callmez
Copy link
Contributor

callmez commented May 9, 2015

Why not make ActiveRecord cache better to use?
like @raminious said

$custome->find()
    ->where(['id' => 1])
    ->cache(3600, $cacheDependency)
    ...
    ->one();

this is better implement than

$result = Post::getDb()->cache(function ($db) {
    return Post::find()->one();
});

@cebe
Copy link
Member

cebe commented May 9, 2015

because the current code is more general and works for all db queries, not only AR. You can also run multiple queries inside the callback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:docs Documentation
Projects
None yet
Development

No branches or pull requests

4 participants