Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Pagination Plugin Laravel Package

saloonphp/pagination-plugin

Adds paginated response support to SaloonPHP. Provides a PaginationPlugin with helpful abstractions to iterate through pages and results when working with APIs that return paginated data, keeping pagination logic out of your connectors and requests.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Package

    composer require saloonphp/pagination-plugin
    
  2. Extend Saloon with the Plugin In your AppServiceProvider or connector setup:

    use Saloon\Saloon;
    use SaloonHttp\Plugins\PaginationPlugin;
    
    public function boot()
    {
        Saloon::extend('pagination', function () {
            return new PaginationPlugin();
        });
    }
    
  3. First Use Case: Basic Pagination Use the paginate() method on a Saloon connector:

    $connector = new GitHubConnector();
    $paginatedUsers = $connector->paginate('users')->all();
    

    Or process items directly:

    $connector->paginate('users')->each(function ($user) {
        // Process each user
    });
    
  4. Key Configuration Specify pagination strategy (default: PageLimitStrategy):

    $connector->withPaginationStrategy(new CursorStrategy());
    

Implementation Patterns

Core Workflows

1. Standard Page/Limit Pagination

$connector->paginate()
    ->page(2)          // Start from page 2
    ->limit(50)        // Fetch 50 items per page
    ->all();           // Get all items

2. Cursor-Based Pagination

$connector->withPaginationStrategy(new CursorStrategy())
    ->paginate()
    ->each(function ($item) {
        // Process item
    });

3. Async Processing with Laravel Queues

$connector->paginate()
    ->chunk(100, function ($items) {
        ProcessItemsJob::dispatch($items);
    });

4. Caching Paginated Responses

$connector->paginate()
    ->cacheFor(3600)   // Cache for 1 hour
    ->all();

5. Custom Pagination Strategies

class CustomStrategy implements PaginationStrategy
{
    public function getNextCursor(array $response): ?string
    {
        return $response['next_cursor'] ?? null;
    }

    public function buildRequest(array $params): array
    {
        return [
            'cursor' => $params['cursor'] ?? null,
            'limit' => $params['limit'] ?? 30,
        ];
    }
}

$connector->withPaginationStrategy(new CustomStrategy());

Integration Tips

Laravel Service Container

Bind the plugin globally in AppServiceProvider:

$this->app->singleton(PaginationPlugin::class, function () {
    return new PaginationPlugin();
});

Testing Paginated Responses

Use Saloon’s MockConnector:

$mock = new MockConnector();
$mock->shouldReceive('send')
     ->andReturn(
         new PaginatedResponse(
             ['user1', 'user2'],
             'next_cursor'
         )
     );

$paginator = $mock->paginate();
$paginator->assertCount(2);

Handling Rate Limits

Combine with Saloon’s RetryPlugin:

$connector->withPlugins([
    new RetryPlugin(),
    new PaginationPlugin(),
]);

Error Handling

Catch pagination-specific exceptions:

try {
    $paginator->all();
} catch (PaginationException $e) {
    Log::error('Pagination failed: ' . $e->getMessage());
}

Gotchas and Tips

Pitfalls

  1. Infinite Loop Detection

    • The plugin automatically detects infinite loops by tracking checksums of request bodies.
    • Gotcha: Disable for async pagination to avoid memory issues:
      $connector->paginate()->disableLoopDetection();
      
  2. Cursor Pagination Edge Cases

    • Some APIs return malformed cursors (e.g., null or empty strings).
    • Fix: Override getNextCursor() in your strategy:
      public function getNextCursor(array $response): ?string
      {
          return $response['pagination']['next'] ?? null;
      }
      
  3. Async Processing Quirks

    • Chunking (->chunk()) processes items in batches but does not guarantee order.
    • Workaround: Use ->each() with a queue job for ordered processing.
  4. Caching Conflicts

    • Cached paginated responses may stale if the API’s data changes.
    • Tip: Use short cache durations (e.g., ->cacheFor(60)) for volatile data.
  5. Type Safety in PHP < 8.5

    • Fluent methods return self but may cause IDE warnings.
    • Fix: Cast to static in your IDE or upgrade to PHP 8.5+.

Debugging Tips

  1. Log Paginated Requests Enable Saloon’s debug mode:

    $connector->withDebug();
    
  2. Inspect Paginator State Dump the paginator object to debug:

    dd($connector->paginate()->getState());
    
  3. Checksum Mismatches If you see InfiniteLoopException, verify:

    • Request bodies are consistent (e.g., no dynamic timestamps).
    • Use ->disableLoopDetection() if false positives occur.
  4. Memory Issues with Large Datasets

    • Symptom: Allowed memory exhausted during ->all().
    • Fix: Use ->chunk() with Laravel Queues:
      $connector->paginate()->chunk(500, function ($items) {
          ProcessItemsJob::dispatch($items);
      });
      

Extension Points

  1. Custom Pagination Strategies Extend PaginationStrategy for non-standard APIs:

    class GraphQLStrategy implements PaginationStrategy
    {
        public function getNextCursor(array $response): ?string
        {
            return $response['data']['pagination']['endCursor'] ?? null;
        }
    
        public function buildRequest(array $params): array
        {
            return [
                'query' => '...',
                'variables' => [
                    'cursor' => $params['cursor'] ?? null,
                    'first' => $params['limit'] ?? 20,
                ],
            ];
        }
    }
    
  2. Middleware for Pagination Add logic before/after pagination:

    $connector->paginate()
        ->before(function () {
            Log::info('Starting pagination');
        })
        ->after(function () {
            Log::info('Pagination complete');
        });
    
  3. Laravel Event Integration Dispatch events during pagination:

    $connector->paginate()
        ->onPage(function ($page) {
            event(new PaginationPageFetched($page));
        });
    
  4. Override Default Config Modify the plugin’s defaults (e.g., max retries):

    $plugin = new PaginationPlugin([
        'max_retries' => 3,
        'chunk_size' => 200,
    ]);
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle