最近在使用Laravel 6.*版本的 API资源功能时,遇到了一个奇怪的错误,程序直接500错误,但是不输出任何错误信息,检查laravel.log以及apache的error.log也没有错误信息,access.log中显示:

“127.0.0.1 – – [14/Apr/2021:16:29:27 +0800] “GET /api/v1/rooms/1 HTTP/1.1” 500 -”

Resources/Room.php代码:

    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'orders' => OrderResource::collection($this->orders),
            'review' => $this->review,
            'price' => $this->price,
            'description' => $this->description,
            'images' => $this->images,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }

经过仔细检查,是因为我在Room Resource中使用的关联资源:orders,同时我项目中还存在Order Resource,在Order Resource中我又使用了关联资源:rooms。

这就导致程序在调用rooms接口时会反复调用room resource以及order resource导致死循环,以至于服务器无法响应,造成500错误。

解决办法是使用条件关联,将上面的代码改为:

    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'orders' => OrderResource::collection($this->whenLoaded('orders')),
            'review' => $this->review,
            'price' => $this->price,
            'description' => $this->description,
            'images' => $this->images,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }

同理,Order Resource中的关联资源rooms也要改为下面的方式:

'room' => new RoomResource($this->whenLoaded('room')),

然后在使用resource时延迟预加载关联:

    public function show(Room $room){
        return $room->load('orders')
    }