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 Bundle Laravel Package

chamber-orchestra/pagination-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require chamber-orchestra/pagination-bundle
    

    Enable the bundle in config/bundles.php:

    return [
        // ...
        ChamberOrchestra\PaginationBundle\PaginationBundle::class => ['all' => true],
    ];
    
  2. First Use Case: Paginate a Doctrine query:

    use ChamberOrchestra\PaginationBundle\Paginator\DoctrinePaginator;
    
    $paginator = new DoctrinePaginator($entityManager->getRepository(Post::class)->findAll(), $request->query->getInt('page', 1), 10);
    $pagination = $paginator->paginate();
    
  3. Twig Rendering: Pass the pagination object to Twig:

    {{ render_pagination(pagination) }}
    

    Override default templates by copying src/Resources/views/ to your project’s templates/bundles/pagination/.


Implementation Patterns

Core Workflows

  1. Page-Based Pagination:

    $paginator = new ArrayPaginator($items, $page = 1, $perPage = 10);
    $pagination = $paginator->paginate();
    
    • Supports lengthAwarePaginate() for total item counts.
  2. Cursor (Keyset) Pagination:

    $paginator = new DoctrineCursorPaginator(
        $entityManager->getRepository(Post::class),
        $request->query->get('cursor'),
        10,
        ['id' => 'ASC']
    );
    $pagination = $paginator->paginate();
    
    • Uses ULID for cursor generation (via ChamberOrchestra\PaginationBundle\Pagination\Cursor).
  3. Type-Based Factory:

    $factory = new PaginationFactory();
    $pagination = $factory->create('doctrine', $queryBuilder, $page, $perPage);
    
    • Supported types: array, doctrine, query.
  4. OptionsResolver Integration: Configure paginator options via Symfony’s OptionsResolver:

    # config/packages/pagination.yaml
    chamber_orchestra_pagination:
        default_per_page: 20
        max_per_page: 100
    

    Override globally or per-paginator:

    $paginator->setOptions(['per_page' => 50]);
    

Integration Tips

  • Doctrine QueryBuilder:

    $qb = $entityManager->createQueryBuilder()
        ->select('p')
        ->from(Post::class, 'p')
        ->orderBy('p.createdAt', 'ASC');
    $pagination = $factory->create('doctrine', $qb, $page, $perPage);
    
  • Custom Twig Extensions: Extend the PaginationExtension to add custom rendering logic:

    use ChamberOrchestra\PaginationBundle\Twig\PaginationExtension;
    
    class CustomPaginationExtension extends PaginationExtension {
        public function getCustomLinks(PaginationInterface $pagination) { ... }
    }
    

    Register as a service and tag it with twig.extension.

  • API Responses: Serialize pagination metadata for APIs:

    return [
        'data' => $pagination->getItems(),
        'meta' => [
            'current_page' => $pagination->getCurrentPage(),
            'per_page' => $pagination->getPerPage(),
            'total' => $pagination->getTotalItems(),
            'last_page' => $pagination->getLastPage(),
        ],
    ];
    

Gotchas and Tips

Pitfalls

  1. Cursor Pagination Quirks:

    • Ensure ordered queries (e.g., ORDER BY id ASC) to avoid inconsistent cursors.
    • ULID cursors are not backward-compatible with UUIDs or other formats.
    • Debug cursor issues with:
      $cursor = $pagination->getCursor();
      $nextCursor = $pagination->getNextCursor();
      
  2. Doctrine Paginator Pitfalls:

    • N+1 Queries: Use join() or fetch('array') to avoid lazy-loading issues.
    • Count Queries: Disable count() for large datasets:
      $paginator->setOptions(['count' => false]);
      
    • DQL Errors: Validate query syntax before passing to the paginator.
  3. Twig Template Overrides:

    • Override templates before rendering:
      {% extends 'bundles/pagination/pagination.html.twig' %}
      
    • Clear cache after overriding:
      php bin/console cache:clear
      
  4. Performance:

    • Page-Based: Use setOptions(['count' => false]) for read-heavy APIs.
    • Cursor-Based: Prefer for infinite scroll; avoid full table scans.

Debugging

  • Log Pagination Events:
    $paginator->setLogger($logger);
    
  • Validate Options:
    $paginator->validateOptions();
    
  • Check for Deprecated Methods: Use phpstan or IDE hints (e.g., ->getItems() vs. ->getData()).

Extension Points

  1. Custom Paginator: Implement PaginatorInterface:

    class CustomPaginator implements PaginatorInterface {
        public function paginate(): PaginationInterface { ... }
    }
    

    Register as a service:

    services:
        ChamberOrchestra\PaginationBundle\Paginator\CustomPaginator:
            tags: ['chamber_orchestra.paginator']
    
  2. Custom Cursor Strategy: Extend CursorStrategyInterface for non-ULID cursors:

    class CustomCursorStrategy implements CursorStrategyInterface {
        public function generateCursor(array $items): string { ... }
        public function parseCursor(string $cursor): array { ... }
    }
    
  3. Modify Pagination Metadata: Override PaginationInterface methods:

    class ExtendedPagination implements PaginationInterface {
        public function getTotalItems(): int { ... }
    }
    

Configuration Quirks

  • Default Values: Override in config/packages/pagination.yaml:
    chamber_orchestra_pagination:
        default_per_page: 15
        max_per_page: 50
        cursor_strategy: 'ulid' # or 'custom'
    
  • Translation Keys: Extend translations in config/packages/translation.yaml:
    imports:
        - { resource: "@PaginationBundle/Resources/translations/messages.en.yaml" }
    
    Override keys in translations/messages.en.yaml:
    pagination:
        previous: '« Previous'
        next: 'Next »'
    

Pro Tips

  • Hybrid Pagination: Combine page-based and cursor pagination for APIs:
    if ($request->query->has('cursor')) {
        $pagination = $cursorPaginator->paginate();
    } else {
        $pagination = $pagePaginator->paginate();
    }
    
  • Pagination Middleware: Add pagination logic to Symfony middleware for global use:
    public function handle(Request $request, callable $next) {
        $request->attributes->set('pagination', $this->createPaginator($request));
        return $next($request);
    }
    
  • Testing: Mock paginators in tests:
    $mockPagination = $this->createMock(PaginationInterface::class);
    $mockPagination->method('getItems')->willReturn([$item1, $item2]);
    
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.
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
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