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

如何为Laravel API资源添加信息?关联项目返回id读取报错

解决Laravel API资源返回关联数据时的「Attempt to read property "id" on array」错误

错误原因分析

  1. 关联定义返回类型错误:User模型的firstProject方法返回的是查询构建器,而非预加载的模型/集合,导致资源处理时数据格式异常。
  2. 资源集合接收数据类型不匹配:UserCollection的with方法中,map->only(['firstProject'])生成嵌套数组集合,而非模型实例集合,传给ProjectCollection后,ProjectResource尝试读取数组的id属性引发错误。
  3. 未预加载关联:控制器未预加载firstProject关联,既导致N+1查询问题,也让资源无法正确获取模型实例。

修复步骤

1. 修正firstProject关联定义

将User模型中的关联改为返回单个模型(符合「第一个项目」的语义),或返回带限制的集合:

// app/Models/User.php
public function firstProject()
{
    // 推荐:返回单个模型(匹配目标JSON中单个项目的场景)
    return $this->hasOne(Project::class)->oldest();
    
    // 若需返回集合(比如保留数组格式):
    // return $this->hasMany(Project::class)->oldest()->limit(1);
}

2. 预加载关联并更新控制器查询

在控制器中预加载firstProject,避免N+1查询,确保关联数据被正确加载:

// app/Http/Controllers/UsersController.php
$users = User::withCount('projects')
    ->with('firstProject') // 预加载第一个项目
    ->latest()
    ->get();

return new UserCollection($users);

3. 修正UserResource的relationships结构

按照目标JSON要求,返回包含项目标识的数组:

// app/Http/Resources/UserResource.php
public function toArray($request)
{
    return [
        "type" => "users",
        "id" => $this->id,
        "attributes" => [
            "name" => $this->name,
            "lastname" => $this->lastname,
            "projects" => $this->whenCounted('projects')
        ],
        "relationships" => [
            "projects" => [
                "data" => $this->whenLoaded('firstProject', function () {
                    // 单个模型场景:用数组包裹资源标识
                    return [
                        ProjectResource::make($this->firstProject)->only('id', 'type')
                    ];
                    // 集合场景:直接映射资源标识
                    // return ProjectResource::collection($this->firstProject)->map->only('id', 'type');
                })
            ]            
        ]
    ];
}

4. 修正UserCollection的with方法生成included数据

收集所有非空的项目模型,用ProjectResource直接生成符合要求的结构:

// app/Http/Resources/UserCollection.php
public function with($request)
{
    // 过滤掉无项目的用户,收集有效项目模型
    $projects = $this->collection
        ->pluck('firstProject')
        ->filter();

    return [
        'included' => ProjectResource::collection($projects)
    ];
}

5. 调整ProjectCollection(可选)

由于目标JSON的included不需要data包裹,ProjectCollection可保持原样,但若仅用于返回完整项目资源,也可以直接使用ProjectResource::collection替代。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 21:36:01