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

Laravel中如何定义关联,获取特定角色用户的最新PostLog

解决Laravel中Post与特定角色用户创建的最新PostLog关联问题

问题分析

你的代码核心问题是将筛选特定角色用户的逻辑放在了ofMany的第二个回调参数中,而该参数的作用是定义排序规则,并非过滤数据。这导致筛选条件未生效,无法正确获取目标PostLog。

正确实现方式

方式一:利用Eloquent关联嵌套(推荐,符合Laratrust使用习惯)

通过whereHas嵌套关联,直接借助Laratrust提供的User与Role关联关系来筛选用户:

class Post extends Model
{
    public function latestAdminPostLog()
    {
        return $this->hasOne(PostLog::class)
            // 筛选出由指定角色用户创建的PostLog
            ->whereHas('user', function ($userQuery) {
                $userQuery->whereHas('roles', function ($roleQuery) {
                    $roleQuery->whereIn('name', ['admin-x', 'admin-y']);
                });
            })
            // 从符合条件的记录中取最新的一条
            ->ofMany(
                ['created_at' => 'max', 'id' => 'max'],
                function ($query) {
                    $query->orderBy('created_at', 'desc')->orderBy('id', 'desc');
                }
            );
    }
}

方式二:保留原whereExists逻辑(调整位置)

如果你更倾向于使用原生SQL的exists查询,只需将筛选逻辑移到ofMany方法之前即可:

class Post extends Model
{
    public function latestAdminPostLog()
    {
        return $this->hasOne(PostLog::class)
            ->whereExists(function ($qry) {
                $qry->select(DB::raw(1))
                    ->from('users')
                    ->join('role_user', 'users.id', '=', 'role_user.user_id')
                    ->join('roles', 'role_user.role_id', '=', 'roles.id')
                    ->whereColumn('users.id', 'post_logs.user_id')
                    ->whereIn('roles.name', ['admin-x', 'admin-y']);
            })
            ->ofMany([
                'created_at' => 'max',
                'id' => 'max'
            ]);
    }
}

关键说明

  • ofMany方法的第一个参数指定取最大值的字段(created_at和id组合确保唯一最新),第二个参数可选,用于明确排序规则,避免歧义。
  • 筛选逻辑必须放在ofMany之前,确保先缩小数据集范围,再从中获取最新记录。

内容的提问来源于stack exchange,提问作者rifqy abdl

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 22:55:27