Laravel - 在模型中缓存外部数据一段时间
Laravel - caching external data in a model for a period of time
模型中的一个字段是从外部资源加载的。从外部资源加载可能会花费很多时间,所以我想尽可能少地这样做。这是我目前所拥有的:
class User extends Model {
private $loaded = false;
private $name = null;
getName(){
if(!$this->loaded){
$this->name = loadNameFromExternalResource($this->id);
$this->loaded = true;
}
return $this->name;
}
}
这在单个请求中运行良好。我可以根据需要多次调用 Auth::user()->getName() 并且只有第一次会导致从外部资源加载。
但这还不够,我还想避免在下一个请求中加载。所以我认为最好将这个字段缓存一段有限的时间,例如一个小时。然后每个请求将从缓存中获取值,并且每小时只有一个请求必须从外部资源加载它。
但我不太明白如何在模型中执行此操作。因为在同一个请求中,不同用户可能有不同的用户模型实例,所以我可以用静态键将它存储在缓存中。我能想到的最好的办法是用用户 ID 存储它,如下所示:
class User extends Model {
private $loaded = false;
private $name = null;
getName(){
if(!$this->loaded){
if(Cache::has('user_name_' . $this->id)){
$this->name = Cache::get('user_name_' . $this->id);
} else {
$this->name = loadNameFromExternalResource($this->id);
Cache::put('user_name_' . $this->id, $this->name, 60);
}
$this->loaded = true;
}
return $this->name;
}
}
但是这个解决方案对我来说有点奇怪。你们有什么感想?可以做得更好吗?
您介绍的使用 Cache facade 的方法是一个典型的解决方案:
- 检查值是否在缓存中
- 如果是 - return
- 如果不是 - 加载,存储在缓存中,return
您只是不需要那个额外的 loaded 标志 - 检查缓存中是否存在值就足够了。
为什么你觉得这有什么不对?
无论如何,如果你使用 Cache facade 的 remember 函数,上面的代码可以大大简化:
private $name;
public function getName() {
if (!$this->name) {
$this->name = Cache::remember('user_name_' . $this->id, 60, function () {
return loadNameFromExternalResource($this->id);
});
}
return $this->name;
}
这将尝试从缓存中获取值。如果存在,它将被 returned。如果没有,将调用提供的回调并将它的值 return 存储在缓存中 60 分钟。
有关详细信息,请参阅文档:https://laravel.com/docs/5.4/cache#storing-items-in-the-cache
模型中的一个字段是从外部资源加载的。从外部资源加载可能会花费很多时间,所以我想尽可能少地这样做。这是我目前所拥有的:
class User extends Model {
private $loaded = false;
private $name = null;
getName(){
if(!$this->loaded){
$this->name = loadNameFromExternalResource($this->id);
$this->loaded = true;
}
return $this->name;
}
}
这在单个请求中运行良好。我可以根据需要多次调用 Auth::user()->getName() 并且只有第一次会导致从外部资源加载。
但这还不够,我还想避免在下一个请求中加载。所以我认为最好将这个字段缓存一段有限的时间,例如一个小时。然后每个请求将从缓存中获取值,并且每小时只有一个请求必须从外部资源加载它。
但我不太明白如何在模型中执行此操作。因为在同一个请求中,不同用户可能有不同的用户模型实例,所以我可以用静态键将它存储在缓存中。我能想到的最好的办法是用用户 ID 存储它,如下所示:
class User extends Model {
private $loaded = false;
private $name = null;
getName(){
if(!$this->loaded){
if(Cache::has('user_name_' . $this->id)){
$this->name = Cache::get('user_name_' . $this->id);
} else {
$this->name = loadNameFromExternalResource($this->id);
Cache::put('user_name_' . $this->id, $this->name, 60);
}
$this->loaded = true;
}
return $this->name;
}
}
但是这个解决方案对我来说有点奇怪。你们有什么感想?可以做得更好吗?
您介绍的使用 Cache facade 的方法是一个典型的解决方案:
- 检查值是否在缓存中
- 如果是 - return
- 如果不是 - 加载,存储在缓存中,return
您只是不需要那个额外的 loaded 标志 - 检查缓存中是否存在值就足够了。
为什么你觉得这有什么不对?
无论如何,如果你使用 Cache facade 的 remember 函数,上面的代码可以大大简化:
private $name;
public function getName() {
if (!$this->name) {
$this->name = Cache::remember('user_name_' . $this->id, 60, function () {
return loadNameFromExternalResource($this->id);
});
}
return $this->name;
}
这将尝试从缓存中获取值。如果存在,它将被 returned。如果没有,将调用提供的回调并将它的值 return 存储在缓存中 60 分钟。
有关详细信息,请参阅文档:https://laravel.com/docs/5.4/cache#storing-items-in-the-cache