Home > other >  Laravel pagination for API
Laravel pagination for API

Time:05-09

I want to make simple pagination for API using Laravel within the format response like this:

{
    "code": 0,
    "message": "success",
    "data": [
        {...},
        {...}
    ],
    "page_context": {
        "page": 2,
        "per_page": 25,
        "has_more_page": false
    }
}

how to achieve this? I don't like Laravel Model::paginate() function.

CodePudding user response:

You could start by creating a helper class:

<?php

namespace App\Helpers;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;

class AppHelper
{
    public static function defaultMetaInput($input) : array
    {
        $page = isset($input['page']) ? (int)$input['page'] : 1;
        $perPage = isset($input['perPage']) ? (int)$input['perPage'] : 50;
        $order = $input['order'] ?? 'created_at';
        $dir = $input['dir'] ?? 'desc';
        $search = isset($input['search']) ? ($input['search']) : '';
        $offset = ($page - 1) * $perPage;
        return [
            'order'     => $order,
            'dir'       => $dir,
            'page'      => $page,
            'perPage'   => $perPage,
            'offset'    => $offset,
            'search'    => $search,
        ];
    }

    public static function additionalMeta($meta, $total)
    {
        $meta['total'] = $total;
        $meta['totalPage'] = ceil( $total / $meta['perPage']);
        if($meta['totalPage'] < $meta['page']){
            $meta['page'] = $meta['totalPage'];
        }
        return $meta;
    }

}

This is just a helper function and I created it, because, on almost every crud, the same metadata might be passed, so this way I could have all these data in a single variable.

Now, on the controller do something like this:

//storing all meta data on a single $meta variable
$meta = AppHelper::defaultMetaInput($request->only(['page', 'perPage', 'order', 'dir','search']));
$query = \DB::table('users as u')
    ->select('u.*');
$query->where(function($q) use($meta){
    $q->orWhere('u.name', 'like', $meta['search'] . '%')
        ->orWhere('u.email', 'like', $meta['search'] . '%');
});

$total = $query->count();

//adding total data on the meta varaible to send on front end,
//so that this data could be used for pagination on front end
$meta = AppHelper::additionalMeta($meta, $total);

$query->orderBy($meta['order'], $meta['dir']);

//if perPage = -, it will returns all data from the table
if ($meta['perPage'] != '-1') {
    $query->offset($meta['offset'])->limit($meta['perPage']);
}
$results = $query->get();
return [
    'results'  => $results,
    'meta'     =>  $meta
];

This is an example, you can tweak data as per your needs. I have used meta in my example you can rename it to any variable, also, for your case has_more_page variable, you can check if $meta['totalPage'] === $meta['page'] then there are no more page.

If you need in exact structure as mentioned in question you can return this instead.

return [
    'code'          => 0,
    'message'       => 'Success',
    'data'          => $results,
    'page_context'  => [
        'page'           => $meta['page'],
        'per_page'       => $meta['perPage'],
        'has_more_page'  => ($meta['totalPage'] === $meta['page'])?false:true,
    ]
];
  • Related