Laravel 缓存已认证用户的关系

Posted

技术标签:

【中文标题】Laravel 缓存已认证用户的关系【英文标题】:Laravel caching authenticated user's relationships 【发布时间】:2016-11-09 23:59:00 【问题描述】:

在我的应用程序中,我使用 Laravel 的身份验证系统,并使用依赖注入(或 Facade)来访问已登录的用户。我倾向于通过我的基本控制器访问登录用户,这样我就可以在我的子类中轻松访问它:

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() 是否返回非空值来通过身份验证是否安全。有没有人遇到过类似的问题?

【问题讨论】:

【参考方案1】:

我建议您使用类似以下的软件包。 https://github.com/spatie/laravel-responsecache

它缓存响应,您可以将其用于用户对象之外。

【讨论】:

【参考方案2】:

好吧,经过一番折腾后,我想出了一个适合自己的解决方案,我想我会分享。

我想我会放弃缓存实际的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 类上实现了几个方法来帮助缓存关系,并为我所有接受 @987654328 的关系实现了 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)

【讨论】:

以上是关于Laravel 缓存已认证用户的关系的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 从学徒到工匠

Laravel中间件,管道之面向切面编程

Laravel中间件,管道之面向切面编程

如何缓存 auth()->user() 与 Laravel 缓存中的角色关系,以减少对数据库的调用?

Laravel Eloquent 负载关系中枢轴关系 [已解决]

5 个非常有用的 Laravel Blade 指令,你用过哪些?