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

Laravel 5.5关联查询问题:获取用户职位的最新作业单

解决Laravel 5.5中获取用户职位及对应最新作业单的问题

嘿,我明白你现在的困扰——想要拿到当前登录用户的所有职位,每个职位只带最新的那一张作业单,之前的尝试要么返回了所有作业单,要么关联调整没到位。别担心,我给你两种靠谱的实现方式,你可以根据自己的业务场景选:

方法一:通过模型关联定义最新作业单

这种方式最符合Laravel的Eloquent关联风格,代码也更优雅:

  1. 在Job模型中新增关联最新作业单的方法
    我们用hasOne关联,配合latest()方法来获取每个职位的最新作业单(默认按created_at降序,如果你需要按更新时间排序,改成latest('updated_at')即可):

    // app/Job.php
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Job extends Model
    {
        // 其他关联和方法...
    
        public function latestJobSheet()
        {
            // 这里默认按created_at取最新,可根据业务调整字段
            return $this->hasOne(JobSheet::class)->latest();
        }
    }
    
  2. 调整User模型的jobs关联,预加载最新作业单
    为了避免N+1查询问题,我们在User的jobs关联里直接预加载latestJobSheet:

    // app/User.php
    namespace App;
    
    use Illuminate\Notifications\Notifiable;
    use Illuminate\Foundation\Auth\User as Authenticatable;
    
    class User extends Authenticatable
    {
        use Notifiable;
    
        // 其他代码...
    
        public function jobs()
        {
            return $this->hasMany(Job::class)->with('latestJobSheet');
        }
    }
    
  3. 在控制器中获取数据
    现在你只需要拿到当前登录用户的jobs,每个job里就会包含latestJobSheet属性,对应最新的作业单:

    // 控制器方法
    public function getUserJobs()
    {
        $user = auth()->user();
        $jobsWithLatestSheet = $user->jobs;
    
        // 后续可以返回视图或者JSON
        return view('jobs.index', compact('jobsWithLatestSheet'));
    }
    

方法二:通过查询构建器直接查询(适合复杂场景)

如果你需要更灵活的查询控制,比如额外筛选作业单字段,可以用子查询关联的方式:

// 控制器方法中直接构建查询
use Illuminate\Support\Facades\DB;

public function getUserJobs()
{
    $jobs = auth()->user()->jobs()
        ->leftJoinSub(
            // 子查询:按job_id分组,获取每个职位的最新作业单ID
            JobSheet::select('job_id', DB::raw('MAX(id) as latest_sheet_id'))
                ->groupBy('job_id'),
            'latest_sheets',
            'jobs.id',
            '=',
            'latest_sheets.job_id'
        )
        // 关联作业单表,拿到最新作业单的详情
        ->leftJoin('job_sheets', 'latest_sheets.latest_sheet_id', '=', 'job_sheets.id')
        // 按需选择字段,注意避免jobs和job_sheets的字段名冲突
        ->select('jobs.*', 'job_sheets.id as sheet_id', 'job_sheets.content', 'job_sheets.created_at as sheet_created_at')
        ->get();

    return view('jobs.index', compact('jobs'));
}

为什么之前的尝试没成功?

你之前可能直接用了with('jobSheets'),这种关联会加载该职位下的所有作业单;而我们上面用hasOne+latest()的组合,本质是告诉Eloquent:每个职位只关联一条最新的作业单,这样就不会返回所有数据了。

内容的提问来源于stack exchange,提问作者Dev.W

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 06:52:45