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

weavers54325's avatar

Paginate while returning array of Api resource objects to the resource collection

I need to send multiple objects to the api resource colection. So I am returning multiple Objects inside array. Everything works fine but not showing any pagination meta data. like Current_page,next_page url etc.

My resource

<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;

    class ServiceProviderCollection extends  Resource
    {

        public function toArray($request)
        { 

            return
            [  

                'name'=>$this->forename,
                'rating'=>$this->rating,
                'price'=>$this->price,
                'distance'=>round($this->distances,1),

            ];
        }
    }

My Controller

$user_city = $userObj->location->city;
$locationObj = Location::whereNotIn('id', $blockeduser)->where('city',$user_city)->first();
$across_city = $locationObj->users()->simplePaginate(20);

    $near_by =  User::join('locations as l', 'users.location_id', '=', 'l.id')
        ->select('users.*', DB::raw('(6371 * acos(cos(radians(' . $coordinates['latitude'] . ')) * cos(radians(`lat`)) * cos(radians(`lng`) - radians(' . $coordinates['longitude'] . ')) + sin(radians(' . $coordinates['latitude'] . ')) * sin(radians(`lat`)))) as distances'))
        ->having('distances', '<', $max_distance)
        ->orderBy('distances', 'ASC')
        ->where('role_id',2)
        ->whereNotIn('id', $blockeduser)
        ->simplePaginate(20);

    return [
                'across_city' => ServiceProviderCollection::collection($across_city),
                'near_by' => ServiceProviderCollection::collection($near_by)
           ];

I want :

{"data":{
    "across_city": [
        {
            "name": "??",
            "rating": 0,
            "price": 0,
            "distance": 0,

        }
    ],
 "links": {
        "first": "",
        "last": "",
        "prev": null,
        "next": ""
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 3,
        "path": "",
        "per_page": 2,
        "to": 2,
        "total": 6
    },
{
    "near_by": [
        {
            "name": "??",
            "rating": 0,
            "price": 0,
            "distance": 0,

        }
    ],
 "links": {
        "first": "",
        "last": "",
        "prev": null,
        "next": ""
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 3,
        "path": "",
        "per_page": 2,
        "to": 2,
        "total": 6
    }
}
0 likes
25 replies
jlrdw's avatar

Does the code work without paginating?

weavers54325's avatar

Yes..Working well with paginate too. The problem is not shown any meta data related to paginate.

1 like
jlrdw's avatar

And this:

Adding Meta Data

Some JSON API standards require the addition of meta data to your resource and resource collections responses. This often includes things like links to the resource or related resources, or meta data about the resource itself. If you need to return additional meta data about a resource, include it in your toArray method. For example, you might include link information when transforming a resource collection:

/**
 * Transform the resource into an array.
 *
 * @param  \Illuminate\Http\Request
 * @return array
 */
public function toArray($request)
{
    return [
        'data' => $this->collection,
        'links' => [
            'self' => 'link-value',
        ],
    ];
}

Have a look : https://github.com/spatie/laravel-json-api-paginate

mahmoudyounes's avatar

Hello everyone i have encountered this problem recently and here are my thoughts

I tired to check if the documentation has something to offer regarding this matter, and the following section pointed me to the solution Eloquent: API Resources #Resource Responses

First they say

As you have already read, resources may be returned directly from routes and controllers

Then they say

However, sometimes you may need to customize the outgoing HTTP response before it is sent to the client. There are two ways to accomplish this

And that's what we want to do, we want to customize the response, as they mentioned there is two way to do this and i used the first one which is

chain the response method onto the resource. This method will return an Illuminate\Http\JsonResponse instance

Now that we can customize the request, what is the customization that we need to do?

We need to manipulate the returned data, so we need to get the data from the response, to do this i checked the api documentation of the instance that the response method return and i found a method that do exactly what we want Illuminate\Http\JsonResponse #Methods getData please note the method first parameter

mixed getData(bool $assoc = false, int $depth = 512) 

which control how data is returned associative or not

And that's it the problem is solved following is a code snippet to demonstrate

$data = SampleModel::paginate(10);
return ['key' => SampleModelResource::collection($data)->response()->getData(true)];
54 likes
wall-e's avatar

Thank you @mhmudyns! Your trick worked for me. Heck it's not even a trick, it's the most elegant solution than what I found on internet whole day. Thanks again!

elo's avatar

Worked for me, many thanks.

I simply chained response()->getData(true) to my collection like this

ModelResource::collection($model)->response()->getData(true)
15 likes
hasanablak's avatar

@elo Why it is don't mention it in Laravel Docs? It is helpful for me thanks.

progalaa's avatar

To make your code clean make a PaginationResource to be used across different collections and make single place for editing pagination details

then inside any resource add your Pagination resource as follow

this is Pagination resource

public function toArray($request) : Array
    {
        return [
            'total' => $this->total(),
            'count' => $this->count(),
            'per_page' => $this->perPage(),
            'current_page' => $this->currentPage(),
            'total_pages' => $this->lastPage()
        ];
    }

and add it to any other collection like this

 public function toArray($request) : Array
    {
        $pagination = new PaginationResource($this);

        return [
            'templates' => $this->collection,
            $pagination::$wrap => $pagination,
        ];
    }

kinson's avatar

Thanks @mhmudyns and @elo! Does anyone have a more elegant way than this to include a status code with the response using these approaches?

I managed to get something working, but the double response seems unintuitive and ...ugly.

    $results = SearchResult::collection(Product::paginate(20));
    return response($results->response()->getData(true), 200);

I know it's not really necessary in this situation, considering these examples are just successful GETs. But it's still something I try to manually specify in responses.

Anyone have any other approaches?

1 like
tetranyble's avatar

I also run into this trouble sometimes ago and here's how i solved it.

  • first create the collection and inside the toArray method return the collection like so:
class CourseCategoryCollection 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 [
            'data' => $this->collection
        ];
    }
}

then in your controller return this:

$courses = auth()->user()->courses()->with(['categories', 'lessons'])
            ->filter($request)->paginate($request->quantity)->withQueryString();

return new CourseCategoryCollection($courses)
hakimfazal426's avatar

I solved this issue very easily. Just pass your paginated variable to resource. this will only update your data field.no return variable required.also no effect on paginations fields.

    $sessions = Session::paginate(10);
    SessionResource::collection($sessions);
    return response()->json([
        'sessions' => $sessions,
    ]);

Please or to participate in this conversation.