Mastering Server‑Side Pagination in FilamentPHP List Components
Learn how FilamentPHP’s List component uses Laravel’s paginator for efficient server‑side pagination, including query‑string handling, custom per‑page settings, and troubleshooting tips.
19 Sept 2026, 01:43 UTC

Problem & Takeaway
When building admin panels with FilamentPHP, you often need to display large datasets efficiently. The List component offers server‑side pagination out of the box, but developers sometimes misconfigure the underlying query or forget how the query string is parsed. The key takeaway: to get smooth pagination, use a query builder or Eloquent model that accepts paginate(), set the perPage option, and let Filament render the toolbar automatically. This guide walks you through the exact steps, shows how to verify the SQL, and explains how to recover when the paginator throws an error.
Desired Outcome
By the end of this article you will:
- Configure a Filament List component to use server‑side pagination with a custom
perPagevalue. - Understand how the
?page=query string is interpreted. - Verify that the generated SQL contains the correct
LIMITandOFFSET. - Know how to troubleshoot common pagination errors.
Prerequisites
- Laravel 10.x or later with FilamentPHP 3.x installed.
- An Eloquent model (e.g.,
App\Models\Post) with a corresponding database table. - Basic knowledge of Laravel routing and Blade components.
- Composer autoloading and database migrations already applied.
Step‑by‑Step Procedure
- Create a List Component
php artisan make:filament-page PostsListThis command generates
app/Filament/Pages/PostsList.phpand a Blade view. Open the PHP file and replace the defaultgetTableQuery()with:public function getTableQuery(): Builder { return Post::query()->orderBy('created_at', 'desc'); }Because the query returns a
Builder, Filament will automatically callpaginate()on it. - Set a Custom
perPageValuepublic function getTableRecordsPerPageSelectOptions(): array { return [5, 10, 20, 50]; }Filament will render a dropdown in the toolbar allowing the user to choose 5, 10, 20, or 50 records per page. The default
perPageis 10. - Enable Query‑String Pagination
Filament automatically reads the
?page=parameter from the URL and passes it to the paginator. No extra code is required. If you need to change the parameter name, you can overridegetTablePaginationPageName():public function getTablePaginationPageName(): string { return 'p'; // uses ?p=2 instead of ?page=2 } - Render the List in a Blade View
@section('content') @endsectionFilament automatically injects the toolbar, page links, and per‑page selector.
- Verify the SQL
In a development environment, enable query logging:
DB::listen(function ($query) { logger()->info($query->sql, $query->bindings); });Navigate to
/posts-list?page=2and check the log. You should see aLIMITandOFFSETthat match the requested page andperPagevalue. - Check the Toolbar Output
On the page, the toolbar will display text like “Showing 6–10 of 37 records” and pagination links. Clicking “Next” should navigate to
?page=3(or?p=3if you changed the name).
Expected Checks
- SQL Verification: The generated query must contain
LIMIT {perPage} OFFSET {(page-1)*perPage}. - Toolbar Consistency: The page count shown in the toolbar matches
LengthAwarePaginator::lastPage(). - URL Parameter Reflection: The
?page=value in the browser address bar matches the page shown. - Per‑Page Dropdown: Selecting a new per‑page value updates the URL to
?page=1&per_page=20and reloads the first page with the new limit.
Recovery Options
- BadException: Query Does Not Support Pagination
If you accidentally pass a raw SQL query or a collection to the List, Filament will throw a
BadExceptionstating that the query cannot be paginated. To recover, ensuregetTableQuery()returns aBuilderorEloquentinstance. - Excessive
perPageValuesSetting
perPageto a very large number can cause memory exhaustion on the server. Use thegetTableRecordsPerPageSelectOptions()method to restrict choices to reasonable values. - Custom Pagination View Mismatch
When overriding the pagination view, ensure the view uses the same query string key (
pageby default). If the view uses a different key, the paginator will not detect the page and will always show the first page. - Client‑Side Pagination on Large Datasets
Filament supports client‑side pagination via
shouldPaginateClientSide(). However, for large tables this can degrade performance. If you notice slow page loads, switch to server‑side by removing that flag.
Conclusion
FilamentPHP’s List component integrates tightly with Laravel’s paginator, making server‑side pagination straightforward. By returning a query builder, setting perPage options, and letting Filament render the toolbar, you get a fully functional paginated table with minimal code. Always verify the generated SQL and toolbar output to ensure the pagination behaves as expected, and use the recovery steps above if you encounter errors.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.