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

如何基于认证用户层级过滤仪表盘全量数据?

解决方案:同时兼容Eloquent与Query Builder的层级化区域数据过滤

针对你遇到的问题,推荐通过自定义Query Builder宏实现全局数据过滤,既能覆盖Eloquent模型又支持原生Query Builder,无需手动修改每个查询。以下是具体实现步骤:

1. 先在用户模型中封装权限判断逻辑

首先在User模型中添加获取用户允许访问区域的方法,根据层级返回对应区域ID数组:

// app/Models/User.php
use App\Models\Region;

class User extends Authenticatable
{
    // ... 其他代码

    // 判断是否为最高层级用户(如应用所有者)
    public function isTopLevel(): bool
    {
        // 根据你的层级规则实现,比如role_level >= 10代表最高级
        return $this->role_level >= 10;
    }

    // 获取用户有权限访问的区域ID数组
    public function getAllowedRegionIds(): array
    {
        if ($this->isTopLevel()) {
            // 最高层级用户返回所有区域ID
            return Region::pluck('id')->toArray();
        }
        // 普通用户返回自身关联的区域ID
        return $this->regions->pluck('id')->toArray();
    }
}

2. 注册全局Query Builder宏

在AppServiceProvider的boot方法中注册自定义宏,让所有Query Builder实例(包括Eloquent生成的)都能调用过滤方法:

// app/Providers/AppServiceProvider.php
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\Auth;

public function boot()
{
    Builder::macro('filterByUserRegion', function ($regionColumn = 'region_id') {
        // 未登录用户直接返回空结果(可根据业务调整)
        if (!Auth::check()) {
            return $this->whereRaw('1=0');
        }

        $user = Auth::user();
        $allowedRegions = $user->getAllowedRegionIds();

        // 无权限区域时返回空结果
        if (empty($allowedRegions)) {
            return $this->whereRaw('1=0');
        }

        // 最高层级用户跳过过滤
        if ($user->isTopLevel()) {
            return $this;
        }

        // 普通用户添加区域过滤条件
        return $this->whereIn($regionColumn, $allowedRegions);
    });
}

3. 全局使用过滤方法

不管是Eloquent模型还是原生Query Builder,都可以直接调用filterByUserRegion()方法实现自动过滤:

// Eloquent示例:获取当前用户有权限的订单
$orders = Order::filterByUserRegion()->get();

// Query Builder示例:获取当前用户有权限的员工数据
$employees = DB::table('employees')->filterByUserRegion('region_id')->get();

// 关联查询示例:指定关联表的区域列
$customerOrders = DB::table('orders')
    ->join('customers', 'orders.customer_id', '=', 'customers.id')
    ->filterByUserRegion('customers.region_id')
    ->select('orders.*')
    ->get();

额外优化建议

  • 缓存区域权限:在getAllowedRegionIds()中添加缓存,避免每次查询都重复获取区域数据:
    public function getAllowedRegionIds(): array
    {
        return cache()->remember("user_regions_{$this->id}", 3600, function () {
            if ($this->isTopLevel()) {
                return Region::pluck('id')->toArray();
            }
            return $this->regions->pluck('id')->toArray();
        });
    }
    
  • 动态指定列名:如果不同表的区域列名不同,调用宏时可以传入自定义列名,比如filterByUserRegion('office_region_id')。

内容的提问来源于stack exchange,提问作者Test Laravel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 10:35:07