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

Laravel 10控制器闭包中访问全局变量$new_period报错排查

问题:Laravel 10控制器change方法报错“Attempt to read property "id" on null”

控制器中的change方法代码如下:

public function change($id)
{

    DB::beginTransaction();
    try{
        $current_period=Period::where('current',true)->first();
        $current_period->current=false;
        $current_period->save();
        $new_period=Period::findOrFail($id);
        $new_period->current=true;
        $new_period->save();

        //set person's memberSince and pay_mode to what is in the person_period pivot table
        $persons=Person::all();
        $persons->each(function ($person,$key){
            global $new_period;
            //dd($new_period->id);
            $pivot=$person->periods()->where('period_id',$new_period->id)->first();
            $person->memberSince=$pivot? $pivot['memberSince']:null;
            $person->pay_mode=$pivot?$pivot['pay_mode']:null;
            $$person->save();
        });
        DB::commit();
        $result=[];
        $ps=PersonResource::collection(Person::all());
        array_push($result, $ps);
        $pr=PeriodResource::collection(all());
        array_push($result,$pr);
        return $result;

    }catch (\Exception $e) {
        DB::rollBack();
        throw $e;
    }
}

执行时返回错误:

message 'Attempt to read property "id" on null'

错误出现在//dd($new_period->id)的下一行,取消注释该行后仍报相同错误,但在each循环外部执行dd($new_period->id)可正常返回$new_period的正确ID,确认变量在外部存在。

原因与解决方案

1. 闭包变量传递错误

PHP闭包默认不会继承父作用域的局部变量,你用global $new_period尝试获取变量是错误的——global用于访问全局命名空间的变量,而$new_period是控制器方法内的局部变量,并非全局变量,因此闭包里的$new_period实际为null,读取id时就会触发报错。

正确的做法是通过use关键字将父作用域的$new_period显式传入闭包:

$persons->each(function ($person,$key) use ($new_period) {
    // ... 内部逻辑
});

2. 代码笔误

代码中$$person->save();多了一个$,属于变量变量语法,会将$person的实例值当作变量名去访问,这显然不符合需求,应该改为$person->save();。

3. 额外的语法错误

PeriodResource::collection(all());中的all()没有指定模型,会调用全局的all()函数(实际不存在),应该改为PeriodResource::collection(Period::all());。

修正后的核心代码片段

$persons=Person::all();
$persons->each(function ($person,$key) use ($new_period) {
    $pivot=$person->periods()->where('period_id',$new_period->id)->first();
    $person->memberSince=$pivot? $pivot['memberSince']:null;
    $person->pay_mode=$pivot?$pivot['pay_mode']:null;
    $person->save();
});
DB::commit();
$result=[];
$ps=PersonResource::collection(Person::all());
array_push($result, $ps);
$pr=PeriodResource::collection(Period::all());
array_push($result,$pr);
return $result;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 14:37:53