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

Laravel全局作用域导致User关联查询冗余,如何规避?

解决方法

方法一:利用认证事件自动加载关联(推荐)

移除User模型中的全局作用域,转而在用户认证成功后自动加载所需关联。这种方式只会给当前认证用户加载关联,不会影响其他User查询。

  1. 在app/Providers/AuthServiceProvider.php的boot方法中添加事件监听:
use Illuminate\Auth\Events\Authenticated;
use Illuminate\Support\Facades\Event;

public function boot()
{
    $this->registerPolicies();

    Event::listen(Authenticated::class, function ($event) {
        // 加载需要的关联
        $event->user->load('subscription.lastpayment', 'tickets');
    });
}
  1. 删除User模型中对应的全局作用域代码。

之后依然可以直接访问auth()->user()->subscription、auth()->user()->tickets,而关联查询(如tickets->user)不会加载额外的冗余关联。

方法二:临时排除全局作用域

如果不想移除全局作用域,可以在查询Tickets时,针对关联的User查询排除该全局作用域:

$tickets = \App\Models\Tickets::with(['user' => function ($query) {
    $query->withoutGlobalScope('subscription');
}])
->with('lastmessage')
->with(['lastmessage.user' => function ($query) {
    $query->withoutGlobalScope('subscription');
}])
->where('subscription_id', auth()->user()->subscription_id)
->get();

这种方式适合只在特定查询中规避全局作用域的场景。

方法三:自定义方法获取带关联的认证用户

移除全局作用域,在User模型中添加一个静态方法,专门用于获取带关联的认证用户:

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

    public static function getAuthUserWithRelations()
    {
        return static::with('subscription.lastpayment', 'tickets')
            ->findOrFail(auth()->id());
    }
}

之后在需要的地方用User::getAuthUserWithRelations()代替auth()->user(),其他User查询(包括关联查询)不受影响。

方法四:修改全局作用域,仅对认证用户查询生效

修改全局作用域的逻辑,只在查询当前认证用户时才加载关联:

protected static function booted()
{
    static::addGlobalScope('subscription', function (Builder $builder) {
        // 仅当当前有认证用户,且查询条件包含当前用户ID时加载关联
        if (auth()->check()) {
            $query = $builder->getQuery();
            // 判断查询是否针对当前认证用户
            $hasUserIdCondition = collect($query->wheres)->some(function ($where) {
                return $where['column'] === 'id' && $where['value'] === auth()->id();
            });

            if ($hasUserIdCondition) {
                $builder->with('subscription.lastpayment', 'tickets');
            }
        }
    });
}

这种方式可以保留全局作用域,但仅对查询当前认证用户的请求生效,关联查询的其他User不会触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 13:45:54