Laravel Resource and Resource Collections

Viewed 55

I'm learning the Laravel Resource API and have setup my controller to pass the data to my Resource and my Resource Collection.

This is the list of servers (index method) with the show method showing the individual server

Controller

Index method

return new DedicatedServerResourceCollection($product->where('parent_id', 1)->with('dedicatedServers')->get());

Show Method

return new DedicatedServerResource(DedicatedServer::findOrfail($id));

I need to format my collection and resource differently. How can I get my Resource Collection to loop through each item and format the changes accordingly?

Resource Collection

return [
    'productTypes' => $this->map(function($data){
    return [
          'id' => $data->id,
          'title' => $data->title,
          'tagline' => $data->tagline,
          'slug' => $data->slug,
          'dedicatedServers' => DedicatedServerResource::collection($this->resource)
           // I need to pass 'dedicatedServers' === $this->dedicated_servers
     ];
    })
  ];

Resource

     return [
            'id' => $this->id,
            'productId' => $this->product_id,
            'type' => $this->type,
            'price' => $this->price,
            'config' => [
                'processorLine1' => $this->processor_line_1,
                'processorLine2' => $this->processor_line_2,
                'memory' => $this->memory,
                'storageLine1' => $this->storage_line_1,
                'storageLine2' => $this->storage_line_2,
                'data' => $this->data,
                'benchmark' => [
                    'benchmark' => $this->benchmark,
                    'benchmarkPercentage' => $this->benchmark_percentage
                ]
            ]
        ];
2 Answers

You should use either "resource file" or "$this->map(...)", not both.

Index Method

return ProductCollection::make(Product::with('dedicatedServers')->get());

ProductCollection

class ProductCollection extends ResourceCollection
{
    public function toArray($request)
    {
        return [
            'productTypes' => $this->collection,
        ];
    }
}

ProductResource

class ProductResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'tagline' => $this->tagline,
            'slug' => $this->slug,
            'dedicated_servers' => $this->whenLoaded('dedicatedServers'),
        ];
    }
}

DedicatedServerResource

class DedicatedServerResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'product_id' => $this->product_id,
            'type' => $this->type,
            'processor_line_1' => $this->processor_line_1,
            'processor_line_2' => $this->processor_line_2,
            'memory' => $this->memory,
            'storage_line_1' => $this->storage_line_1,
            'storage_line_2' => $this->storage_line_2,
            'data' => $this->data,
            'benchmark' => $this->benchmark,
            'product' => ProductResource::make($this->whenLoaded('product')),
        ];
    }
}

Note: Prefer to use $this->whenLoaded('dedicatedServers') instead of $this->dedicatedServers to avoid n+1 problem.

You might want to create a different resource class for the DedicatedServer model, like SecondDedicatedServerResource.

Related