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

使用Octane::concurrently时模型观察者中Auth::user()为空的问题

问题原因

Octane的concurrently方法会把闭包放到独立的执行线程/进程里跑,这些异步任务不会自动继承当前请求的认证上下文。Laravel的Auth::user()依赖请求生命周期内的上下文绑定,异步闭包里没有这个上下文,所以返回null。

解决方案

方案1:直接传用户ID,跳过观察者里的Auth依赖

在主线程先拿到用户ID,创建模型时直接把created_by塞进$data里,不用在观察者里依赖Auth:

$userId = Auth::id();
[$contract, $contractType] = Octane::concurrently([
    fn() => Contract::create(array_merge($data, ['created_by' => $userId]), $loadRelationships),
    fn() => collect(ContractTypeEnum::cases())
        ->filter(fn($enum) => strtolower($enum->label()) === strtolower($data['contract_type']))
        ->first()
        ->name,
]);

这种方式最简单直接,还能减少观察者对全局状态的依赖。

方案2:在异步闭包里手动绑定认证用户

如果一定要在观察者里用Auth::user(),可以在主线程先拿到用户实例,然后在闭包里手动设置给Auth:

$user = Auth::user();
[$contract, $contractType] = Octane::concurrently([
    fn() => {
        Auth::setUser($user);
        return Contract::create($data, $loadRelationships);
    },
    fn() => collect(ContractTypeEnum::cases())
        ->filter(fn($enum) => strtolower($enum->label()) === strtolower($data['contract_type']))
        ->first()
        ->name,
]);

注意:如果用的是Swoole这类Octane驱动,要确保User模型能被序列化(Laravel默认的User模型是支持的)。

方案3:给观察者加 fallback 逻辑

修改观察者的creating方法,优先用模型上已经设置的created_by,没有的话再尝试从Auth拿:

// 观察者代码
public function creating(ContractModel $contract)
{
    if (empty($contract->created_by) && Auth::check()) {
        $contract->created_by = Auth::user()->id;
    }
}

然后调用的时候和方案1一样,在主线程传created_by就行,这样不管是同步还是异步调用都能兼容。

注意点
  • Octane异步任务的上下文是完全独立的,除了你显式传进去的变量,别指望能直接拿到主线程的请求、Session、Auth这些东西。
  • 尽量少在异步闭包里依赖全局状态,能用参数传的就用参数传,代码更健壮。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 04:06:20