你怎么会忘记 Laravel 中缓存的 Eloquent 模型?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19542890/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How would you forget cached Eloquent models in Laravel?
提问by Peter Fox
Theoretical question on Laravel here.
关于 Laravel 的理论问题在这里。
So Example of the caching I'd do is:
所以我要做的缓存示例是:
Article::with('comments')->remember(5)->get();
Ideally I'd like to have an event for Article updates that when the ID of a instance of that model (that's already cached) is updated I want to forget that key (even if it's the whole result of the query that's forgotten instead of just that one model instance), it is possible to do so?
理想情况下,我希望有一个用于文章更新的事件,当该模型的实例(已经缓存)更新时,我想忘记该键(即使它是查询的整个结果被遗忘而不是仅仅那个模型实例),有可能这样做吗?
If not is there some way to implement this reasonably cleanly?
如果没有,是否有某种方法可以合理干净地实现这一点?
回答by Syed I.R.
So i was looking for an answer to the same question as OP but was not really satisfied with the solutions. So i started playing around with this recently and going through the source code of the framework, I found out that the remember()
method accepts second param called key
and for some reason it has not been documented on their site(Or did i miss that?).
所以我正在寻找与 OP 相同的问题的答案,但对解决方案并不满意。所以我最近开始玩这个并浏览框架的源代码,我发现该remember()
方法接受调用的第二个参数,key
并且由于某种原因它没有在他们的网站上记录(或者我错过了那个?)。
Now good thing about this is that, The database builder uses the same cache driver which is configured under app/config/cache.php
Or should i say the same cache system that has been documented here - Cache. So if you pass min and key to remember()
, you can use the same key to clear the cache using Cache::forget()
method and in fact, you can pretty much use all the Cache
methods listed on the official site, like Cache::get()
, Cache::add()
, Cache::put()
, etc. But i don't recommend you to use those other methods unless you know what you're doing.
现在关于这一点的好处是,数据库构建器使用在 Cache 下配置的相同缓存驱动程序app/config/cache.php
或者我应该说这里记录的相同缓存系统 - Cache。所以,如果你通过分和关键remember()
,你可以使用相同的密钥使用清除缓存Cache::forget()
方法,事实上,你几乎可以使用所有Cache
的列出的方法官方网站,像Cache::get()
,Cache::add()
,Cache::put()
等等。但我不建议您使用其他方法,除非您知道自己在做什么。
Here's an example for you and others to understand what i mean.
这是一个示例,您和其他人可以理解我的意思。
Article::with('comments')->remember(5, 'article_comments')->get();
Article::with('comments')->remember(5, 'article_comments')->get();
Now the above query result will be cached and will be associated with the article_comments
key which can then be used to clear it anytime (In my case, I do it when i update).
现在上面的查询结果将被缓存并与article_comments
密钥相关联,然后可以随时使用它来清除它(在我的情况下,我在更新时这样做)。
So now if i want to clear that cache regardless of how much time it remembers for. I can just do it by calling Cache::forget('article_comments');
and it should work just as expected.
所以现在如果我想清除缓存,不管它记得多少时间。我可以通过调用来完成它Cache::forget('article_comments');
,它应该按预期工作。
Hope this helps everyone :)
希望这对大家有帮助:)
回答by Glad To Help
I think a good way to do is like this:
我认为一个好的办法做到像这样:
$value = Cache::remember('users', $minutes, function()
{
return DB::table('users')->get();
});
and then use Model Observersto detect the event of updating the model
然后使用Model Observers检测更新模型的事件
class UserObserver {
public function saving($model)
{
//
}
public function saved($model)
{
// forget from cache
Cache::forget('users');
}
}
User::observe(new UserObserver);
回答by tharumax
Currently there are no easy way. However I found this workaround, which so far worked for me.
目前没有简单的方法。但是我找到了这个解决方法,到目前为止它对我有用。
First you have to extend Illuminate\Database\Query\Builder
.
首先,您必须扩展Illuminate\Database\Query\Builder
.
<?php
class ModifiedBuilder extends Illuminate\Database\Query\Builder {
protected $forgetRequested = false;
public function forget()
{
$this->forgetRequested = true;
}
public function getCached($columns = array('*'))
{
if (is_null($this->columns)) $this->columns = $columns;
list($key, $minutes) = $this->getCacheInfo();
// If the query is requested ot be cached, we will cache it using a unique key
// for this database connection and query statement, including the bindings
// that are used on this query, providing great convenience when caching.
$cache = $this->connection->getCacheManager();
$callback = $this->getCacheCallback($columns);
if($this->forgetRequested) {
$cache->forget($key);
$this->forgetRequested = false;
}
return $cache->remember($key, $minutes, $callback);
}
}
Then you have to create new class which extends Eloquent Model.
然后你必须创建一个扩展 Eloquent 模型的新类。
<?php
class BaseModel extends Eloquent {
protected function newBaseQueryBuilder() {
$conn = $this->getConnection();
$grammar = $conn->getQueryGrammar();
return new ModifiedBuilder($conn, $grammar, $conn->getPostProcessor());
}
}
Now when creating Eloquent Models, instead of extending Eloquent
Models extend newly created BaseModel
.
现在在创建 Eloquent 模型时,不是扩展Eloquent
模型而是扩展新创建的BaseModel
.
Now you can remember
query result as usual.
现在您可以remember
照常查询结果了。
YourModel::remember(10)->get();
When you want to discard the cached result all you have to do is
当你想丢弃缓存的结果时,你所要做的就是
YourModel::forget()->get();
If you remember the result previously, after clearing the cached result, model will continue to remember the result for that amount of time.
如果您之前记得结果,清除缓存的结果后,模型将继续记住该时间段的结果。
Hope this helps.
希望这可以帮助。
回答by Lionel Morrison
I was testing for debug mode. So I found that if you put a test for app.debug in a constructor you are able to clear the cache associated with a key. Saves you having to duplicate the code for every function.
我正在测试调试模式。所以我发现如果你在构造函数中对 app.debug 进行测试,你就可以清除与键关联的缓存。让您不必为每个函数复制代码。
class Events {
public function __construct() {
if (\Config::get('app.debug')) {
Cache::forget('events');
}
}
public static function all() {
$events = \DB::table('events as e')
->select('e.*')
->where('enabled', 1)
->remember(30, 'events')
->get();
return $events;
}
}