You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中如何像缓存Auth::user()一样缓存角色数据查询?

问题

我开发的Laravel应用中,用户凭证存储在users表,不同角色对应独立的数据表(如admins、customers等)。Auth::user()在应用中多次调用仅执行一次数据库查询,但使用Admin::where('user_id', Auth::id())->first()或通过User模型关联调用Auth::user()->admin()时,每次调用都会执行查询;在模型访问器处理多行数据时,该查询甚至会重复执行数百次。请问如何像缓存Auth::user()一样缓存这类角色数据查询?

解决方案

1. 给User模型加自定义缓存属性

直接在User模型里封装角色数据的缓存逻辑,利用模型实例的内存存储,同一个请求内只会查询一次:

// app/Models/User.php
public function admin()
{
    return $this->hasOne(Admin::class);
}

public function customer()
{
    return $this->hasOne(Customer::class);
}

// 自定义缓存的角色属性
public function getCachedRoleAttribute()
{
    if (!isset($this->attributes['cached_role'])) {
        // 根据实际角色判断逻辑切换查询
        if ($this->role === 'admin') {
            $this->attributes['cached_role'] = $this->admin;
        } elseif ($this->role === 'customer') {
            $this->attributes['cached_role'] = $this->customer;
        }
    }
    return $this->attributes['cached_role'];
}

之后调用Auth::user()->cached_role即可,同一个用户实例只会触发一次关联查询。

2. 登录时预加载角色并绑定到Auth实例

在用户登录完成后,直接预加载对应角色的关联数据,后续调用无需再查库:

// app/Http/Controllers/Auth/LoginController.php
protected function authenticated(Request $request, $user)
{
    // 根据用户角色预加载对应关联
    match($user->role) {
        'admin' => $user->load('admin'),
        'customer' => $user->load('customer'),
    };
    // 把预加载的模型存到用户实例的自定义属性
    $user->setAttribute('current_role', $user->{$user->role});
}

之后直接用Auth::user()->current_role就能拿到缓存的角色数据。

3. 请求级全局缓存

利用Laravel容器的请求周期缓存,封装成全局可用的辅助方法,整个请求内只查一次:

// 可以放在app/helpers.php里
function current_user_role()
{
    return app()->remember('current_user_role', function () {
        $user = Auth::user();
        if (!$user) return null;
        
        return match($user->role) {
            'admin' => Admin::where('user_id', $user->id)->first(),
            'customer' => Customer::where('user_id', $user->id)->first(),
            default => null,
        };
    });
}

任何地方调用current_user_role(),同一个请求内只会执行一次数据库查询。

4. 优化循环内的访问器逻辑

如果是在模型访问器处理批量数据时重复查询,不要在访问器内直接调用角色查询,而是在控制器层先获取角色数据,再传递给集合处理:

public function index()
{
    $currentRole = Auth::user()->cached_role;
    // 批量处理数据时直接复用已获取的角色数据
    $items = Item::all()->map(function ($item) use ($currentRole) {
        $item->custom_field = $currentRole->permission;
        return $item;
    });
    
    return view('items.index', compact('items'));
}

内容的提问来源于stack exchange,提问作者Yousef Aburayyan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 18:50:44