Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ahmeda's avatar

Add custom pagination meta to Laravel Resources API

I have this custom pagination in AppServiceProvider.php

Builder::macro('pagination', function($limit = null, $page = null){
    $page = $page ?: 1;
    $limit = $limit ?: 50;
    $total = $this->count();
    $items = $this->offset(($page - 1) * $limit)->limit($limit)->get();
    $firstItem = count($items) > 0 ? ($page - 1) * $limit + 1 : null;

    return [
        'data' => $items->toArray(),
        'total' => $total,
        'from' => $firstItem,
        'to' => count($items) > 0 ? ($firstItem + $items->count() - 1) : null,
        'last_page' =>  max((int) ceil($total / $limit), 1),
    ];
});

This pagination is working just fine but I got a problem when I use it with Laravel reoucres API like in the following query:

$posts = auth()->user()->posts()->pagination($request->per_page, $request->page);

return PostsResource::collection($posts['data'])->additional([
    'total' => $posts['total'],
    'last_page' => $posts['last_page'],
    'from' => $posts['from'],
    'to' => $posts['to'],
]);

Each time i need to use Laravel reources i have to add additional to pass pagiantion stuff there!

Is there any way to merge Laravel reources with my custom pagiantion and do not need to write additional each time ?

0 likes
4 replies
vincent15000's avatar

You can add a resource collection with your additional meta data.

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class PostsCollection 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 parent::toArray($request);
    }
    
    /**
     * Get additional data that should be returned with the resource array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function with($request)
    {
        return [
			'total' => ...
        ];
    }
}

Then in your controller you have just to replace the resource by the collection.

return new PostsCollection($posts['data']);

The PostsCollection will automatically retrieve the PostsResource.

1 like
ahmeda's avatar

@vincent15000 with($request) will be repeated in each collection... is there a way to put in a place and pass him the meta ?

1 like
vincent15000's avatar

@ahmeda What is in the with() method will be added to the collection, but not to each model in the collection.

You can for example wrap the additional datas like this.

public function with($request)
{
   return [
		'meta' => [
			'title' => ...
		]
   ];
}
martinbean's avatar

@ahmeda Why have you created that macro that literally does the same as what Laravel’s native pagination does, as far as I can see?

1 like

Please or to participate in this conversation.