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