- How do I install juampi92/cursor-pagination?
- Install it with Composer using composer require juampi92/cursor-pagination. The package registers a service provider through Laravel auto-discovery, so no manual provider registration is normally needed. After that you swap paginate() for the package's cursor pagination method on the endpoints where you want cursor-based navigation. Check the package's Composer constraints against your PHP and Laravel versions before committing, since its last release dates to November 2020.
- Does juampi92/cursor-pagination support Laravel 9, 10, and 11?
- Treat it as a legacy compatibility shim: its last release was in November 2020, so its constraints target PHP 7.x and older Laravel versions. Laravel 8 and later ship native cursorPaginate(), which covers the same use case and is actively maintained. If you are on Laravel 9, 10, or 11, use the native implementation rather than adding this dependency. Verify constraints in a branch before assuming it will install on a modern stack.
- What is the difference between this package and Laravel's native cursorPaginate()?
- Functionally they are very close: both provide cursor-based pagination with opaque tokens instead of offset/limit. This package predates native support and was built as a drop-in for API controllers, inspired by Stripe's cursor style. On Laravel 8+ the native cursorPaginate() is the better default because it is maintained by the framework and tested against current PHP versions. The package's remaining value is Laravel 7 and below, or unusual query shapes native pagination does not cover.
- How do I use cursor pagination in a Laravel API controller?
- Replace paginate() with the cursor pagination call on the query you already return from your controller, then return the paginator as JSON. Clients pass the cursor token back as a query parameter to fetch the next page, and the response includes the next and previous cursors. Keep your response shape stable so consumers are not surprised when you later swap to native cursorPaginate(). Because the integration surface is small, a parity proof of concept on one or two endpoints takes hours, not weeks.
- Are the cursors opaque and encoded, or can clients read them?
- Cursors are encoded into an opaque string so clients treat them as tokens rather than parsing internal column values. That is the Stripe-style contract: the token is an implementation detail and can change without breaking API consumers. The encoding is not a security boundary, so do not put sensitive data in the sort key, and validate incoming tokens before decoding. Document the cursor contract, including sort order and tiebreaker, for your own team.
- What happens if a client sends an invalid or malformed cursor?
- An undecodable token can surface as a 4xx or even a 5xx if you do not handle it defensively. Wrap cursor decoding in your controller or a form request so malformed input returns a clean 422 or 400 rather than a stack trace. Add integration tests around the encode and decode path, including truncated and tampered tokens. The package itself is unmaintained, so this defensive handling is your responsibility, not the vendor's.
- Is cursor pagination better than offset pagination for large datasets and infinite scrolling?
- Yes for deep pages: offset pagination gets slower and less stable the further a client scrolls, while cursor pagination seeks from a known position using an indexed sort key. That makes it a good fit for infinite scroll feeds and large API result sets. The package's overhead is negligible; the real performance factor is having a stable, unique sort key backed by a composite index. If you are on Laravel 8+, you get the same benefit from native cursorPaginate() without an extra dependency.
- Which database drivers and query types does it support?
- Database-driver support is not well documented and the repository is archived, so verify against every driver you target rather than assuming parity with native pagination. Cursor pagination in general struggles with groupBy, unions, distinct, and raw expressions, because the cursor needs deterministic ordering. Run a proof of concept on representative queries, including multi-column and custom cursor cases, before rolling it out. If a query shape is unsupported, keep that endpoint on offset pagination or extract the logic you need into an internally owned module.
- How do I avoid duplicate or missing rows during concurrent writes with cursor pagination?
- Cursor stability depends on ordering by a unique, immutable tiebreaker such as an auto-incrementing ID alongside your timestamp column. Without that tiebreaker, rows inserted or updated during pagination can appear twice or be skipped entirely. This is a property of your sort key and indexes, not something the package enforces for you. Document the ordering contract per endpoint and add a composite index on the ordering columns.
- Is juampi92/cursor-pagination still maintained, and what should I use instead?
- No: the last release was 2020-11-24, the repository is archived, and there is no vendor triage or security patching. Do not adopt it net-new. On Laravel 8 and above, migrate endpoints to native cursorPaginate() behind feature flags after a parity check, then remove the dependency. If you genuinely need behavior native pagination lacks, fork the logic into an internally owned module with CI, pinned dependencies, and a named owner rather than depending on an abandoned package.