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,
]
];