0

Laravel pagination has different structure when returned by itself vs. through an API resource.

return $query->paginate(request('per_page'));

returns pagination with this structure:

{
    "current_page": 1,
    "data":[...],
    "first_page_url": "http://user-service.test/api/users?page=1",
    "from": 1,
    "last_page": 1,
    "last_page_url": "http://user-service.test/api/users?page=1",
    "next_page_url": null,
    "path": "http://user-service.test/api/users",
    "per_page": 15,
    "prev_page_url": null,
    "to": 10,
    "total": 10
}

On the other hand, sending the paginator through an API resource like this:

return new UserCollection($query->paginate(request('per_page')));

returns this structure:

{
"data":[...],
"links": {
    "first": "http://user-service.test/api/users/searches?page=1",
    "last": "http://user-service.test/api/users/searches?page=6",
    "prev": null,
    "next": "http://user-service.test/api/users/searches?page=2"
    },
"meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 6,
    "path": "http://user-service.test/api/users/searches",
    "per_page": "1",
    "to": 1,
    "total": 6
    }
}

I need to have the same structure for both types. Am I doing something wrong?

3 Answers 3

2

After some digging I found a solution for this, hope it's helpful.

So this line is fine

return new UserCollection($query->paginate(request('per_page')));

As long as you change the UserCollection toArray() function to:

    public function toArray($request)
    {
        return [
            'current_page' => $this->currentPage(),
            'data' => $this->collection->toArray(),
            'first_page_url' => $this->url(1),
            'from' => $this->firstItem(),
            'last_page' => $this->lastPage(),
            'last_page_url' => $this->url($this->lastPage()),
            'next_page_url' => $this->nextPageUrl(),
            'path' => $this->path(),
            'per_page' => $this->perPage(),
            'prev_page_url' => $this->previousPageUrl(),
            'to' => $this->lastItem(),
            'total' => $this->total(),
        ];
    }

This snippet of code is from the original implementation of LengthAwarePaginator, this way you could have consistent pagination for both collections and simple use of LengthAwarePaginator (->paginate() function).

Sign up to request clarification or add additional context in comments.

Comments

0

That's because you created an Eloquent Resource.

As you can see in the doc, it's taking $this->collection and wraps it around a customer format.

If you wish to have the same format, you do not need to return the UserCollection, just return $query->paginate(request('per_page'))

Without seeing more of your code and how are you using your UserCollection class, it's hard to recommend to keep it or remove it. Also, please read the high overview of that concept here

Comments

0

just do this

public function __construct($resource)
{
    $this->pagination = [
        'total' => $resource->total(),
        'per_page' => $resource->perPage(),
        'current_page' => $resource->currentPage(),
        'last_page' => $resource->lastPage(),
        'from' => $resource->firstItem(),
        'to' => $resource->lastItem(),
        'count' => $resource->count(),
        'total_pages' => $resource->lastPage()
    ];

    $resource = $resource->getCollection();

    parent::__construct($resource);
}

/**
 * Transform the resource collection into an array.
 *
 * @param  Request  $request
 * @return array
 */
public function toArray($request): array
{
    $this->pagination['data'] = $this->collection;

    return [
        $this->pagination
    ];
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.