Framework: Pagination data missing from api resource.

Created on 26 Apr 2020  路  7Comments  路  Source: laravel/framework

  • Laravel Version: 7.8.1
  • PHP Version: 7.4.2
  • Database Driver & Version: MySql & 5.7

Description:

When sending an eloquent query to an api resource with pagination the pagination data is missing from the result.

Laravel 6.x

{
  "current_page": 1,
  "data": [
    {
      "id": 10000196,
      "name": "John Doe",
    }
  ],
  "first_page_url": "http://www.mysite.com/users?page=1",
  "from": 1,
  "next_page_url": "http://www.mysite.com/users?page=2",
  "path": "http://www.mysite.com/users",
  "per_page": 1,
  "prev_page_url": null,
  "to": 1
}

Laravel 7.x

[
  {
    "id": 10000196,
    "name": "John Doe",
  }
]

Steps To Reproduce:

Using a fresh laravel app with the default user table and at least one user in the database.

$resource = \App\Http\Resources\User::collection(\App\User::query()->paginate(1));

dd($resource->toJson());
bug

Most helpful comment

Hey there, we document that you need to use an actual collection to do this:

image

Note the section about no extra metadata being added.

Pagination documentation:

image

All 7 comments

Hey there,

Can you first please try one of the support channels below? If you can actually identify this as a bug, feel free to report back and I'll gladly help you out and re-open this issue.

Thanks!

Experiencing a similar issue when using JsonResource::collection.

Here's a reproduction for Laravel 6 and 7:

Project Setup

$ git clone [email protected]:laravel/laravel
$ git checkout (6.x|7.x)
$ cd laravel
$ nano .env
$ composer install
$ php artisan key:generate 
$ php artisan migrate
$ php artisan tinker

>>> User::create(['name' => 'Test', 'email' => '[email protected]', 'password' => Hash::make('secret') ]);
[!] Aliasing 'User' to 'App\User' for this Tinker session.
=> App\User {#3016
     name: "Test",
     email: "[email protected]",
     updated_at: "2020-04-28 02:40:07",
     created_at: "2020-04-28 02:40:07",
     id: 1,
   }

Laravel 6

>>> \Illuminate\Http\Resources\Json\JsonResource::collection(User::paginate(10))->toJson()
=> "{"current_page":1,"data":[{"id":1,"name":"Test","email":"[email protected]","email_verified_at":null,"created_at":"2020-04-28 02:51:20","updated_at":"2020-04-28 02:51:20"}],"first_page_url":"http:\/\/localhost?page=1","from":1,"last_page":1,"last_page_url":"http:\/\/localhost?page=1","next_page_url":null,"path":"http:\/\/localhost","per_page":10,"prev_page_url":null,"to":1,"total":1}"

>>> \Illuminate\Http\Resources\Json\JsonResource::collection(User::paginate(10))->response()->getContent()
=> "{"data":[{"id":1,"name":"Test","email":"[email protected]","email_verified_at":null,"created_at":"2020-04-28 02:51:20","updated_at":"2020-04-28 02:51:20"}],"links":{"first":"http:\/\/localhost?page=1","last":"http:\/\/localhost?page=1","prev":null,"next":null},"meta":{"current_page":1,"from":1,"last_page":1,"path":"http:\/\/localhost","per_page":10,"to":1,"total":1}}"

Laravel 7

>>> \Illuminate\Http\Resources\Json\JsonResource::collection(User::paginate(10))->toJson()
=> "[{"id":1,"name":"Test","email":"[email protected]","email_verified_at":null,"created_at":"2020-04-28T02:40:07.000000Z","updated_at":"2020-04-28T02:40:07.000000Z"}]"

>>> \Illuminate\Http\Resources\Json\JsonResource::collection(User::paginate(10))->response()->getContent()
=> "{"data":[{"id":1,"name":"Test","email":"[email protected]","email_verified_at":null,"created_at":"2020-04-28T02:40:07.000000Z","updated_at":"2020-04-28T02:40:07.000000Z"}],"links":{"first":"http:\/\/localhost?page=1","last":"http:\/\/localhost?page=1","prev":null,"next":null},"meta":{"current_page":1,"from":1,"last_page":1,"path":"http:\/\/localhost","per_page":10,"to":1,"total":1}}"

As a note, it may be that ResourceCollection is the preferred approach according to the documentation.

https://laravel.com/docs/7.x/eloquent-resources#pagination

It does still leave questions around the usage of JsonResource::collection.

Re-opening this. Currently a bit strapped on time so appreciating anyone helping out here.

Hey there, we document that you need to use an actual collection to do this:

image

Note the section about no extra metadata being added.

Pagination documentation:

image

Although even this works for me on latest Laravel 7:

    return UserResource::collection(User::paginate(10));

Thanks, returning paginated resources from routes does work 馃憤

Route::get('/users', function() {
    return \Illuminate\Http\Resources\Json\JsonResource::collection(
        \App\User::paginate(10)
    );
});

Calling toJson directly still returns only the paginated rows without meta. Personally, I don't use this feature but some might outside the context of controllers.

    return UserResource::collection(User::paginate(10))->toJson();

Takeaway for me is - in those scenarios, just use resource collections.

Was this page helpful?
0 / 5 - 0 ratings