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

Laravel多表关联权限需求:登录用户仅查看所属职位对应的JOBS数据

实现用户仅查看所属职位对应JOBS数据的方案

问题背景

我拥有USERS、DESIGNATIONS和JOBS三张数据表,其中USERS与DESIGNATIONS通过中间表designation_user建立多对多关联;JOBS表通过designation_id字段与DESIGNATIONS表关联。需求为:用户登录后,仅能查看其所属职位对应的JOBS数据。现有表结构及模型代码如下,请协助实现该功能。

现有表结构

designation_user中间表

id | user_id | designation_id

jobs表核心字段

designation_id

修正模型关联错误

首先需要纠正当前模型的关联方法:USERS与DESIGNATIONS是多对多关系,当前代码中使用belongsTo(一对一/一对多关联)是错误的,应改为belongsToMany:

USER模型修正后代码

public function designations() {
    return $this->belongsToMany(Designation::class, 'designation_user');
}

DESIGNATION模型修正后代码

public function users() {
    return $this->belongsToMany(User::class, 'designation_user');
}

权限控制实现方案

方案1:通过用户模型关联直接获取

在USER模型中新增关联方法,直接关联到用户可访问的JOBS:

public function accessibleJobs() {
    return $this->hasManyThrough(
        Job::class,
        Designation::class,
        'id', // DESIGNATIONS表与中间表关联的字段
        'designation_id', // JOBS表与DESIGNATIONS表关联的字段
        'id', // USER表与中间表关联的字段
        'id' // 中间表与DESIGNATIONS表关联的字段
    );
}

使用时直接调用登录用户的关联:

// 获取当前登录用户可查看的所有JOBS数据
$jobs = auth()->user()->accessibleJobs()->get();

方案2:查询构造器手动筛选

若无需新增模型关联,可直接通过查询构造器基于用户职位ID筛选:

// 获取当前用户的所有职位ID集合
$designationIds = auth()->user()->designations()->pluck('designations.id');

// 筛选出对应职位的JOBS数据
$jobs = Job::whereIn('designation_id', $designationIds)->get();

方案3:全局作用域自动过滤

如果希望所有JOBS查询都自动应用权限控制,可给Job模型添加全局作用域:

// 在Job模型中添加全局作用域
protected static function booted() {
    static::addGlobalScope('user_designation', function ($query) {
        // 仅对已登录用户生效
        if (auth()->check()) {
            $designationIds = auth()->user()->designations()->pluck('designations.id');
            $query->whereIn('designation_id', $designationIds);
        }
    });
}

之后直接查询Job模型会自动过滤数据:

// 自动返回当前登录用户可查看的JOBS数据
$jobs = Job::get();

内容的提问来源于stack exchange,提问作者Ryan R

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 14:15:32