在我的应用程序中,我使用Laravel的身份验证系统,并使用依赖注入(或外观)来访问登录用户。我倾向于通过我的基本控制器访问登录用户,以便我可以在我的子类中轻松访问它:
class Controller extends BaseController
{
protected $user;
public function __construct()
{
$this->user = 'Auth::user();
}
}
我的用户有许多不同的关系,我倾向于像这样急切加载:
$this->user->load(['relationshipOne', 'relationshipTwo']);
由于在这个项目中,我希望收到持续的高流量,我希望使应用程序尽可能流畅和高效地运行,因此我希望实现一些缓存。
理想情况下,我需要能够避免重复查询数据库,特别是对于用户的相关记录。因此,我需要研究在加载关系后缓存用户对象。
我有这样的想法:
public function __construct()
{
$userId = 'Auth::id();
if (!is_null($userId)) {
$this->user = 'Cache::remember("user-{$userId}", 60, function() use($userId) {
return User::with(['relationshipOne', 'relationshipTwo'])->find($userId);
});
}
}
但是,我不确定是否'Auth::id()
返回非 null 值来通过身份验证是否安全。有没有人遇到过类似的问题?
我建议您使用如下所示的软件包。 https://github.com/spatie/laravel-responsecache
它缓存响应,您可以将其用于用户对象以外的更多内容。
好吧,经过一番混乱,我想我会分享一个解决方案。
我以为我会放弃缓存实际的User
对象,只是让身份验证正常进行,只专注于尝试缓存用户的关系。这感觉像是一种非常肮脏的方式,因为我的逻辑在模型中:
class User extends Model
{
// ..
/**
* This is the relationship I want to cache
*/
public function related()
{
return $this->hasMany(Related::class);
}
/**
* This method can be used when we want to utilise a cache
*/
public function getRelated()
{
return 'Cache::remember("relatedByUser({$this->id})", 60, function() {
return $this->related;
});
}
/**
* Do something with the cached relationship
*/
public function totalRelated()
{
return $this->getRelated()->count();
}
}
就我而言,我需要能够在User
模型中缓存相关项,因为我在用户内部有一些使用该关系的方法。就像上面totalRelated
方法的非常简单的例子一样(我的项目有点复杂)。
当然,如果我的User
模型上没有这样的内部方法,那么从模型外部调用关系并缓存它(例如在控制器中)
class MyController extends Controller
{
public function index()
{
$related = 'Cache::remember("relatedByUser({$this->user->id})", 60, function() {
return $this->user->related;
});
// Do something with the $related items...
}
}
同样,这对我来说不是最好的解决方案,我愿意尝试其他建议。
干杯
编辑:我更进一步,在我的父Model
类上实现了几个方法来帮助缓存关系,并为我所有接受$useCache
参数的相关关系实现了getter方法,使事情更加灵活:
父模型类:
class Model extends BaseModel
{
/**
* Helper method to get a value from the cache if it exists, or using the provided closure, caching the result for
* the default cache time.
*
* @param $key
* @param Closure|null $callback
* @return mixed
*/
protected function cacheRemember($key, Closure $callback = null)
{
return Cache::remember($key, Cache::getDefaultCacheTime(), $callback);
}
/**
* Another helper method to either run a closure to get a value, or if useCache is true, attempt to get the value
* from the cache, using the provided key and the closure as a means of getting the value if it doesn't exist.
*
* @param $useCache
* @param $key
* @param Closure $callback
* @return mixed
*/
protected function getOrCacheRemember($useCache, $key, Closure $callback)
{
return !$useCache ? $callback() : $this->cacheRemember($key, $callback);
}
}
我的用户类:
class User extends Model
{
public function related()
{
return $this->hasMany(Related::class);
}
public function getRelated($useCache = false)
{
return $this->getOrCacheRemember($useCache, "relatedByUser({$this->id})", function() {
return $this->related;
});
}
}
用法:
$related = $user->getRelated(); // Gets related from the database
$relatedTwo = $user->getRelated(true); // Gets related from the cache if present (Or from database and caches result)