Search code examples
laravel

How to customize Laravel's Collection API resources?


I tried the following but it doesn't work:

ArticleController.php:

public function index()
    {
        $articles = Article::latest()->paginate(10);
        return ArticleCollection::collection($articles);
    }

ArticleCollection.php:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class ArticleCollection extends ResourceCollection
{
    /**
     * Transform the resource collection into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
     */
    public function toArray($request)
    {
        return [
            'name' => $this->title,
            'subtitle' => $this->subtitle,
            'cover' => $this->cover,
        ];
    }
}

This of transforming the model seems to work for a single model, but not for a collection. How should i customize which fields will be returned when working with collections API resources?


Solution

  • Let your DB query define the final fields

    Check this way, in your ArticleController create a query with a select() method in which you define which DB fields are sent to the ArticleCollection.

    The collection will only take care of returning the that that was given to it!

    public function index()
    {
        return new ArticleCollection(
            Article::latest()->select(['name', 'subtitle', 'cover'])->paginate(10)
        );
    }
    

    Result query

    select
      `name`,
      `subtitle`,
      `cover`
    from
      `articles`
    order by
      `created_at` desc
    limit
      10 offset 0
    

    ArticleCollection

    This file can be set as default, this allows you to dynamically set values passed from the select() method on the ArticleController.

    class ArticleCollection extends ResourceCollection
    {
        public function toArray($request)
        {
            return parent::toArray($request);
        }
    }