Kirill Fuchs
Kirill Fuchs

Reputation: 13696

Returning paginated eloquent models with custom JSON schema?

I'm working on an API in Laravel 4, and right now when I return paginated info in JSON format it comes back in this specific format:

    {
        "Photos":{
            "total":1,
            "per_page":15,
            "current_page":1,
            "last_page":1,
            "from":1,
            "to":1,
            "data":[
                {
                    "id":3,
                    "moreInfo":"..."
                }
            ]
        }
    }

But I want my API to instead return the information in this format:

    {
        "total":1,
        "per_page":15,
        "current_page":1,
        "last_page":1,
        "from":1,
        "to":1,
        "Photos":[
            {
                "id":3,
                "moreInfo":"..."
            }
        ]
    }

The relevant code looks like:

    if (Input::has('page')) {
        $limit = (Input::get('limit')) ? Input::get('limit') : 15;

        return Response::json([
            'Photos' => $photos->paginate($limit)->toArray()
        ]);
    }

Upvotes: 4

Views: 5098

Answers (4)

Vedmant
Vedmant

Reputation: 2591

With the latest Laravel 10 the following solution is most appropriate:

app/Pagination/MyPaginator.php

<?php

namespace App\Pagination;

use Illuminate\Pagination\LengthAwarePaginator;

class MyPaginator extends LengthAwarePaginator
{
    /**
     * Get the instance as an array.
     *
     * @return array
     */
    public function toArray()
    {
        return [
            'data'         => $this->items->toArray(),
            'current_page' => $this->currentPage(),
            'from'         => $this->firstItem(),
            'last_page'    => $this->lastPage(),
            'per_page'     => $this->perPage(),
            'to'           => $this->lastItem(),
            'total'        => $this->total(),
        ];
    }
}

Then in app\Providers\AppServiceProvider.php:

use App\Pagination\MyPaginator;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Contracts\Pagination\LengthAwarePaginator as LengthAwarePaginatorContract;

public function register()
{
    $this->app->alias(MyPaginator::class, LengthAwarePaginator::class);
    $this->app->alias(MyPaginator::class, LengthAwarePaginatorContract::class);
}

Upvotes: 1

Marianela Diaz
Marianela Diaz

Reputation: 109

In Laravel 9 this works different, to customize the response for Paginator the code should looks like this:

$myCommunityActivities = CommunityActivity::where('member_id', Auth::user()->id)->paginate(10);

$results = [
   'total' => $myCommunityActivities->total(),
   'per_page' => $myCommunityActivities->perPage(),
   'current_page' => $myCommunityActivities->currentPage(),
   'last_page' => $myCommunityActivities->lastPage(),
   'activities' => $myCommunityActivities->items()
];

return response()->json($results, 200);

Upvotes: 0

Kirill Fuchs
Kirill Fuchs

Reputation: 13696

At first I didn't realize how simple this actually is, I tried getting data via the Pagination->getItems() and Pagination->getCollection().

I realized all I had to do was get the ['data'] section from the pagination. My code now looks like:

    if (Input::has('page')) {
        $limit = (Input::get('limit')) ? Input::get('limit') : 15;

        $pagedPhotos = $photos->paginate($limit);

        return Response::json([
            'total' => $pagedPhotos->getTotal(),
            'per_page' => $pagedPhotos->getPerPage(),
            'current_page' => $pagedPhotos->getCurrentPage(),
            'last_page' => $pagedPhotos->getLastPage(),
            'from' => $pagedPhotos->getFrom(),
            'to' => $pagedPhotos->getTo(),
            'Photos' => $photos->paginate($limit)->toArray()['data']
        ]);
    }

Upvotes: 8

Marc B
Marc B

Reputation: 360792

So strip out the photos component:

return Response::json($photos->paginate($limit)->toArray())

Upvotes: 2

Related Questions