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

Laravel启用preventAccessingMissingAttributes后出现resource属性错误

解决Laravel开启preventAccessingMissingAttributes()后的资源集合错误

问题描述

在AppServiceProvider.php的boot方法中添加Model::preventAccessingMissingAttributes();后,API返回如下错误:

The attribute [resource] either does not exist or was not retrieved for model [App\Models\Vehicle].

错误出现在使用自定义DefaultCollection返回分页数据的场景,相关代码如下:

DefaultCollection.php

<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;

class DefaultCollection extends ResourceCollection
{
     /**
     * The resource collection class to be used.
     *
     * @var string
     */
    protected $resourceClass;

    /**
     * Set the resource collection class.
     *
     * @param  string  $resourceClass
     * @return $this
     */
    public function setResourceClass(string $resourceClass)
    {
        $this->resourceClass = $resourceClass;

        return $this;
    }

    /**
     * Customize the pagination information for the resource.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  array $paginated
     * @param  array $default
     * @return array
     */
    public function paginationInformation($request, $paginated, $default)
    {
        $default['count'] = $default['meta']['total'];
        unset($default['meta']);

        return $default;
    }

    /**
     * Transform the resource collection into an array.
     *
     * @return array<int|string, mixed>
     */
    public function toArray(Request $request): array
    {
        $resourceClass = $this->resourceClass;

        return [
            'data' => $resourceClass::collection($this->collection),
        ];
    }
}

VehicleController.php

public function index()
{
    $vehicles = Vehicle::with(['manufacturer', 'colors'])
        ->latest()
        ->paginate(50);
    $collection = new DefaultCollection($vehicles);
    $collection->setResourceClass(VehicleResource::class);
    return $collection;
}

问题原因

开启preventAccessingMissingAttributes()后,Laravel会严格禁止访问模型不存在的属性。自定义的DefaultCollection重写了toArray方法,且未正确设置Laravel资源集合所需的$collects属性,导致分页响应逻辑错误地尝试访问模型的resource属性(该属性不存在于Vehicle模型中)。

解决方案

修改DefaultCollection,使用Laravel资源集合的默认toArray逻辑,并通过$collects属性指定要使用的资源类,替代自定义的$resourceClass:

修改后的DefaultCollection.php

<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;

class DefaultCollection extends ResourceCollection
{
    /**
     * The resource class that this collection wraps.
     *
     * @var string
     */
    public $collects;

    /**
     * Set the resource class for the collection.
     *
     * @param  string  $collects
     * @return $this
     */
    public function setResourceClass(string $collects)
    {
        $this->collects = $collects;

        return $this;
    }

    /**
     * Customize the pagination information for the resource.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  array $paginated
     * @param  array $default
     * @return array
     */
    public function paginationInformation($request, $paginated, $default)
    {
        $default['count'] = $default['meta']['total'];
        unset($default['meta']);

        return $default;
    }

    /**
     * Transform the resource collection into an array.
     *
     * @return array<int|string, mixed>
     */
    public function toArray(Request $request): array
    {
        // 使用父类默认的toArray逻辑,确保分页响应能正确处理资源转换
        return parent::toArray($request);
    }
}

优化控制器调用(可选)

也可以直接在构造函数中传入资源类,省略setResourceClass方法:

// DefaultCollection中添加构造函数
public function __construct($resource, string $collects)
{
    parent::__construct($resource);
    $this->collects = $collects;
}

// VehicleController中调用
public function index()
{
    $vehicles = Vehicle::with(['manufacturer', 'colors'])
        ->latest()
        ->paginate(50);
    return new DefaultCollection($vehicles, VehicleResource::class);
}

这样修改后,Laravel的分页响应逻辑会通过$collects属性正确指定每个模型对应的资源类,不会再尝试访问模型不存在的resource属性,同时保留了自定义分页信息的功能。

内容的提问来源于stack exchange,提问作者studio-pj

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 12:35:54