Eloquent中遍历Resource集合时foreach返回null值问题排查
Laravel资源集合遍历无法获取自定义字段
day_name的问题 问题场景
在Laravel项目中,通过Eloquent关联查询获取HourAttendance数据,使用HourAttendanceResource转换后,直接返回资源集合能看到包含day_name的有效数据,但遍历集合时通过属性访问day_name始终返回null。
相关代码
数据查询与资源转换
$h_attendance=HourAttendance::with('adm','paper','faculty','program','student') ->whereRelation('adm','batch_id',$batch) ->whereMonth('date',$month) ->whereYear('date', $year) ->get(); $data=HourAttendanceResource::collection($h_attendance);
HourAttendanceResource的toArray方法
public function toArray($request) { $f=$this->student->first_name ?? ''; $m=$this->student->middle_name ?? ''; $l=$this->student->last_name ?? ''; return [ 'student_id'=>$this->student_id, 'admission_number'=>$this->adm->admission_number, 'std_name'=> $f.$m.$l, 'roll_no'=>$this->adm->roll_no ?? $this->adm->admission_number, 'register_number'=>$this->adm->register_number, 'id'=>$this->id, 'date'=>$this->date, 'time_slot_id'=>$this->time_slot_id, 'program_type'=>$this->program_type, 'program_id'=>$this->program_id, 'attendance'=>$this->attendance, 'user_id'=>$this->user_id, 'timestamp'=>$this->timestamp, 'faculty_name'=>$this->faculty->faculty_name, 'attendancev'=>$this->when($this->attendance,function() { switch($this->attendance){ case(1): $att='P'; break; case(2): $att='L'; break; case(0): $att='A'; break; default: $att=''; break; } return $att; }) ?? '', 'paper_name'=>$this->when($this->program_type != null,$this->program_type == 1 || $this->program_type == 3 ? $this->paper->paper_name ?? null : null), 'paper_teacher'=>$this->when($this->program_id != null,$this->program_type==1 || $this->program_type==3 ? $this->faculty->faculty_name:null ?? null), 'paper_teacher_id'=>$this->when($this->program_type != null ,$this->program_type==1 || $this->program_type==3 ? $this->paper->faculty_id ?? null: null ), 'programe_name'=>$this->when($this->program_type != null,$this->program_type==2 ? $this->program->program_name ?? null: null) , 'programe_description'=>$this->when($this->program_type != null,$this->program_type==4 ? $this->program->description ?? null: null) , 'is_marked'=>1, 'day_name'=>carbon::parse($this->date)->dayName, ]; }
遍历代码(存在问题)
foreach($data as $dat){ $day[]=$dat->day_name; } return dd($day);
直接返回资源集合的有效数据示例
{ "student_id": 1370, "admission_number": "D1010", "std_name": "Ahsana Sherin", "roll_no": 9, "register_number": "DM1001", "id": 325, "date": "2022-07-01", "time_slot_id": 2, "program_type": 3, "program_id": 911, "attendance": 1, "user_id": 1131, "timestamp": "2022-07-01 15:11:54", "faculty_name": "AMAL Raj", "attendancev": "P", "paper_name": "New course01", "paper_teacher": "AMAL Raj", "paper_teacher_id": 1096, "programe_name": null, "programe_description": null, "is_marked": 1, "day_name": "Friday" }
问题原因
day_name是在Resource的toArray方法中生成的自定义输出字段,并非模型本身的属性。Laravel的Resource实例(包括集合中的单个Resource对象),其自定义字段存储在内部转换后的数组中,无法直接通过对象属性访问($dat->day_name),只能通过数组方式或调用toArray方法获取。
解决方案
方案1:通过数组方式访问字段
利用Resource实现的ArrayAccess接口,直接以数组形式获取字段:
foreach($data as $dat){ $day[]=$dat['day_name']; } return dd($day);
方案2:先转换为数组再处理
先将整个资源集合转换为数组,再提取day_name字段,推荐使用集合的pluck方法简化操作:
// 转换为数组 $transformedData = $data->toArray(request()); // 提取day_name $day = collect($transformedData)->pluck('day_name')->toArray(); dd($day);
方案3:为Resource添加访问器(可选)
如果需要频繁通过属性访问自定义字段,可以在Resource类中添加对应访问器:
public function getDayNameAttribute() { return carbon::parse($this->date)->dayName; }
之后即可通过$dat->day_name访问,但注意此方法需要确保date字段已加载,且会增加Resource的复杂度,仅在必要时使用。
内容的提问来源于stack exchange,提问作者adithyan.cs
相关产品推荐
相关产品推荐

