laravel-5.5

Customising Laravel 5.5 Api Resource Collection pagination


I have been working with laravel api resource. By default laravel provides links and meta as shown below.

"links": {
    "first": "https://demo.test/api/v2/taxes?page=1",
    "last": "https://demo.test/api/v2/taxes?page=4",
    "prev": null,
    "next": "https://demo.test/api/v2/taxes?page=2"
},
"meta": {
   "current_page": 1,
   "from": 1,
   "last_page": 4,
   "path": "https://demo.test/api/v2/taxes",
   "per_page": 2,
   "to": 2,
   "total": 8
} 

But I don't want this, insted i want something like

"pagination": {
  "total": 8,
  "count": 8,
  "per_page": 25,
  "current_page": 1,
  "total_pages": 1
}

I'm able to get this info but if I do return TaxResource::collection($taxes);, I won't get this. Even I have custom collection method

 public static function collection($resource)
    {
       $resource->pagination = [
        'total' => $resource->total(),
        'count' => $resource->count(),
        'per_page' => $resource->perPage(),
        'current_page' => $resource->currentPage(),
        'total_pages' => $resource->lastPage()
       ];
        return parent::collection($resource);
    }

It is not giving what I want. But if I reference through (TaxResource::collection($taxes))->pagination; I'm able to get that. But I want it to be returned when I do return TaxResource::collection($taxes);


Solution

  • I was interested in your question and spent some time resolving it. I guess there are a lot of work to be done to improve Eloquent: API Resources' functionality in the future.

    In order to resolve it I must use Resource Collections instead of Resources:

    However, if you need to customize the meta data returned with the collection, it will be necessary to define a resource collection

    php artisan make:resource Tax --collection
    

    or

    php artisan make:resource TaxCollection
    

    Route:

    Route::get('/get-taxes', function () {
        $taxes = Taxes::paginate();
        return new TaxCollection($taxes);
    });
    

    TaxCollection.php:

    <?php
    
    namespace App\Http\Resources;
    
    use Illuminate\Http\Resources\Json\ResourceCollection;
    
    class TaxCollection extends ResourceCollection
    {        
        public function toArray($request)
        {
            return [
            'data' => $this->collection,
            'pagination' => [
                'total' => $this->total(),
                'count' => $this->count(),
                'per_page' => $this->perPage(),
                'current_page' => $this->currentPage(),
                'total_pages' => $this->lastPage()
            ],
        ];
        }  
    
        // Using Laravel < 5.6
        public function withResponse($request, $response)
        {
            $originalContent = $response->getOriginalContent();
            unset($originalContent['links'],$originalContent['meta']);
            $response->setData($originalContent);
        }
    
        // Using Laravel >= 5.6
        public function withResponse($request, $response)
        {
            $jsonResponse = json_decode($response->getContent(), true);
            unset($jsonResponse['links'],$jsonResponse['meta']);
            $response->setContent(json_encode($jsonResponse));
        }
    }
    

    This solve the problem but now there are new one: Unlike Resources I don't know how to modify toArray fields in Resource Collections, the manual shows only example with 'data' => $this->collection where we send not modified collection (Resource Collections allows us change meta data). So If we use just Resource then we can modify collection data but not meta data.