companue / auto-paginate
Laravel package for automatic API pagination with infinite scroll support. Provides reusable traits and helpers for consistent paginated responses across all API endpoints.
Installs: 4
Dependents: 1
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/companue/auto-paginate
Requires
- php: ^8.1
- illuminate/database: ^10.0|^11.0|^12.0
- illuminate/pagination: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
Requires (Dev)
- orchestra/testbench: ^10.0
- phpunit/phpunit: ^10.0
This package is auto-updated.
Last update: 2025-12-14 10:09:53 UTC
README
A Laravel package that provides automatic API pagination with infinite scroll support. Add pagination to any controller endpoint with just one line of code!
Features
- ✅ One-Line Integration - Add pagination with a single method call
- ✅ Automatic Scroll Detection - Perfect for infinite scroll UIs
- ✅ Consistent Response Format - Standardized across all endpoints
- ✅ Backward Compatible - Supports both paginated and non-paginated responses
- ✅ Flexible - Works with Query Builders and Collections
- ✅ Type Safe - Full PHP type hints and return types
- ✅ Zero Configuration - Works out of the box
Installation
Install via Composer:
composer require companue/auto-paginate
The package will automatically register its service provider.
Quick Installation
Run the installation command for an interactive setup:
php artisan auto-paginate:install
This will guide you through two installation options:
- Publish AutoPaginatedController (Recommended) - Extend your controllers from it
- Update base Controller.php - Inject trait directly into the base controller
Manual Installation Options
Option 1: Publish AutoPaginatedController (Recommended)
Publish the AutoPaginatedController to your project:
php artisan vendor:publish --tag=auto-paginate-controller
Or use the command with the default option:
php artisan auto-paginate:install
This creates app/Http/Controllers/API/AutoPaginatedController.php with pagination methods built-in.
Then update your API controllers to extend it:
use App\Http\Controllers\API\AutoPaginatedController; class YourController extends AutoPaginatedController { public function index(Request $request) { $query = YourModel::query(); return response()->json( $this->indexResponse($query, YourResource::class, $request) ); } }
Alternative: Use Trait Directly
If you prefer not to use AutoPaginatedController, add the trait to your controllers:
use Companue\AutoPaginate\Traits\PaginatesQueries; class YourController extends Controller { use PaginatesQueries; // Same usage as above }
Option 2: Update Base Controller (Direct Injection)
Inject the trait directly into your base Controller.php:
php artisan auto-paginate:install --base-controller
This will:
- Create a backup of your
Controller.phpatapp/Http/Controllers/Controller.php.backup - Add
use Companue\AutoPaginate\Traits\PaginatesQueries;import statement - Add
PaginatesQueriesto your existing trait list in the Controller class
Before:
<?php namespace App\Http\Controllers; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Routing\Controller as BaseController; class Controller extends BaseController { use AuthorizesRequests, DispatchesJobs, ValidatesRequests; }
After:
<?php namespace App\Http\Controllers; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Routing\Controller as BaseController; use Companue\AutoPaginate\Traits\PaginatesQueries; class Controller extends BaseController { use AuthorizesRequests, DispatchesJobs, ValidatesRequests, PaginatesQueries; }
After installation, all your controllers will have pagination methods without extending anything:
class YourController extends Controller { public function index(Request $request) { $query = YourModel::query(); return response()->json( $this->indexResponse($query, YourResource::class, $request) ); } }
Usage
Basic Usage
Add the trait to your base controller or any specific controller:
use Companue\AutoPaginate\Traits\PaginatesQueries; class Controller extends BaseController { use PaginatesQueries; }
Then in your controller methods:
public function index(Request $request) { $query = YourModel::query()->orderBy('created_at', 'desc'); return response()->json( $this->indexResponse($query, YourResource::class, $request) ); }
That's it! Your endpoint now supports pagination.
With Filters
public function index(Request $request) { $query = YourModel::query(); // Apply filters if ($request->has('status')) { $query->where('status', $request->get('status')); } // Apply ordering $query->orderBy('created_at', 'desc'); // Return with automatic pagination return response()->json( $this->indexResponse($query, YourResource::class, $request) ); }
Custom Page Size
public function index(Request $request) { $query = YourModel::query(); // Apply pagination with custom default (20 items per page) $paginator = $this->applyPagination($query, $request, 20); return response()->json( $this->paginatedResponse($paginator, YourResource::class) ); }
Without Resource Transformation
public function index(Request $request) { $query = YourModel::query(); // Pass null to return raw data without resource transformation return response()->json( $this->indexResponse($query, null, $request) ); }
Paginating Collections
public function index(Request $request) { // Get and process collection $items = YourModel::query() ->get() ->map(function($item) { $item->calculated_field = $item->price * 1.1; return $item; }); // Apply pagination to the collection $paginator = $this->applyPagination($items, $request); return response()->json( $this->paginatedResponse($paginator, YourResource::class) ); }
API Requests
Paginated Requests
GET /api/items?page=1
GET /api/items?page=2&per_page=20
GET /api/items?filter=active&page=1&per_page=10
Non-Paginated Requests
GET /api/items?paginate=false
Response Format
Paginated Response
{
"data": [
{ "id": 1, "name": "Item 1" },
{ "id": 2, "name": "Item 2" }
],
"pagination": {
"current_page": 1,
"last_page": 5,
"per_page": 15,
"total": 75,
"from": 1,
"to": 15,
"has_more": true
}
}
Non-Paginated Response
[
{ "id": 1, "name": "Item 1" },
{ "id": 2, "name": "Item 2" }
]
Available Methods
indexResponse($query, $resourceClass = null, $request = null)
Smart method that automatically handles pagination based on request parameters.
Parameters:
$query- Query Builder or Collection$resourceClass- Optional resource class for transformation$request- Optional request object (defaults torequest())
Returns: Array with data and pagination info, or raw collection
applyPagination($query, $request = null, $defaultPerPage = 15)
Manually apply pagination to a query or collection.
Parameters:
$query- Query Builder or Collection$request- Optional request object$defaultPerPage- Default items per page (default: 15, max: 100)
Returns: LengthAwarePaginator
paginatedResponse($paginator, $resourceClass = null)
Build standardized paginated response from a paginator.
Parameters:
$paginator- LengthAwarePaginator instance$resourceClass- Optional resource class
Returns: Array with data and pagination metadata
shouldPaginate($request = null)
Check if pagination should be applied based on request.
Parameters:
$request- Optional request object
Returns: Boolean
Configuration
The package works with sensible defaults:
- Default page size: 15 items
- Maximum page size: 100 items
- Pagination parameter:
page - Page size parameter:
per_page
Frontend Integration
Perfect for infinite scroll implementations:
// React/Vue example const loadMore = () => { if (pagination.has_more && !loading) { fetchData({ page: pagination.current_page + 1 }); } };
Migration from Manual Pagination
Before:
$perPage = $request->get('per_page', 15); $records = YourModel::query()->paginate($perPage); $items = YourResource::collection($records->items()); return response()->json([ 'data' => $items, 'pagination' => [ 'current_page' => $records->currentPage(), 'last_page' => $records->lastPage(), // ... more fields ] ]);
After:
$query = YourModel::query(); return response()->json( $this->indexResponse($query, YourResource::class, $request) );
Testing
composer test
Requirements
- PHP 8.1 or higher
- Laravel 10.0, 11.0, or 12.0
License
The MIT License (MIT). Please see License File for more information.
Credits
Support
For support, please open an issue on GitHub or contact mimalefdal@gmail.com