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

Doctrine Collections Adapter Laravel Package

pagerfanta/doctrine-collections-adapter

Adapter connecting Pagerfanta pagination to Doctrine Collections. Paginate ArrayCollection and other Collection implementations with limit/offset slicing and count support, enabling easy integration of Doctrine collection data into Pagerfanta-based UIs.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install Dependencies

    composer require pagerfanta/pagerfanta pagerfanta/doctrine-collections-adapter
    

    Ensure doctrine/collections is installed (automatically included via pagerfanta/doctrine-collections-adapter).

  2. Basic Pagination Setup

    use Pagerfanta\Pagerfanta;
    use Pagerfanta\Adapter\DoctrineCollectionAdapter;
    
    // Assume $doctrineCollection is a Doctrine\Common\Collections\Collection
    $adapter = new DoctrineCollectionAdapter($doctrineCollection);
    $pagerfanta = new Pagerfanta($adapter);
    
    // Set pagination parameters
    $pagerfanta->setMaxPerPage(20); // Items per page
    $pagerfanta->setCurrentPage(1); // Current page
    
  3. First Use Case: Paginating a Doctrine Repository Result

    $entityManager = $this->getDoctrine()->getManager();
    $users = $entityManager->getRepository(User::class)->findAll(); // Returns ArrayCollection
    $adapter = new DoctrineCollectionAdapter($users);
    $pagerfanta = new Pagerfanta($adapter);
    
    // Get current page results
    $currentPageUsers = $pagerfanta->getCurrentPageResults();
    

Implementation Patterns

Workflows

  1. Controller Integration

    public function index(Request $request)
    {
        $users = $this->userRepository->findAll();
        $adapter = new DoctrineCollectionAdapter($users);
        $pagerfanta = new Pagerfanta($adapter);
    
        // Handle pagination parameters from request
        $page = $request->query->getInt('page', 1);
        $perPage = $request->query->getInt('per_page', 20);
        $pagerfanta->setMaxPerPage($perPage);
        $pagerfanta->setCurrentPage($page);
    
        return view('users.index', [
            'users' => $pagerfanta->getCurrentPageResults(),
            'pagerfanta' => $pagerfanta,
        ]);
    }
    
  2. Service Layer Abstraction Create a dedicated service to encapsulate pagination logic:

    class DoctrinePaginatorService
    {
        public function paginate(Collection $collection, int $page, int $perPage): Pagerfanta
        {
            $adapter = new DoctrineCollectionAdapter($collection);
            $pagerfanta = new Pagerfanta($adapter);
            $pagerfanta->setMaxPerPage($perPage);
            $pagerfanta->setCurrentPage($page);
            return $pagerfanta;
        }
    }
    
  3. API Response Integration

    public function apiUsers(Request $request)
    {
        $users = $this->userRepository->findAll();
        $pagerfanta = $this->doctrinePaginator->paginate($users, $request->page, $request->per_page);
    
        return response()->json([
            'data' => $pagerfanta->getCurrentPageResults(),
            'meta' => [
                'total' => $pagerfanta->getNbResults(),
                'pages' => $pagerfanta->getNbPages(),
                'current_page' => $pagerfanta->getCurrentPage(),
            ],
        ]);
    }
    

Integration Tips

  1. Leverage Pagerfanta’s Built-in Features

    • Use getLinks() for pagination links (supports Bootstrap, Twig, etc.):
      $pagerfanta->getLinks('bootstrap_4');
      
    • Access metadata like total items, pages, etc.:
      $pagerfanta->getNbResults();
      $pagerfanta->getNbPages();
      
  2. Combine with Doctrine Criteria

    $criteria = Criteria::create()
        ->where(Criteria::expr()->eq('status', 'active'))
        ->orderBy(['createdAt' => Criteria::DESC]);
    
    $filteredCollection = $collection->matching($criteria);
    $adapter = new DoctrineCollectionAdapter($filteredCollection);
    
  3. Dependency Injection Register the service in Laravel’s container (AppServiceProvider):

    $this->app->bind(DoctrinePaginatorService::class, function ($app) {
        return new DoctrinePaginatorService();
    });
    
  4. Form Request Validation Validate pagination parameters in a FormRequest:

    public function rules()
    {
        return [
            'page' => 'integer|min:1',
            'per_page' => 'integer|min:1|max:100',
        ];
    }
    

Gotchas and Tips

Pitfalls

  1. Memory Usage

    • Issue: Doctrine Collections are loaded entirely into memory before pagination.
    • Fix: Limit maxPerPage (e.g., 50–100 items) and avoid for large datasets (>10K items).
    • Workaround: Use SQL-level pagination with QueryBuilder if possible:
      $queryBuilder = $entityManager->createQueryBuilder();
      $queryBuilder->select('u')
                   ->from(User::class, 'u')
                   ->setFirstResult(($page - 1) * $perPage)
                   ->setMaxResults($perPage);
      
  2. Empty Collections

    • Issue: Pagerfanta throws OutOfRangeException if the collection is empty.
    • Fix: Validate the collection before pagination:
      if ($collection->isEmpty()) {
          return response()->json(['data' => []]);
      }
      
  3. Page Number Validation

    • Issue: Invalid page numbers (e.g., page=999) may cause errors.
    • Fix: Constrain the current page:
      $maxPages = ceil($pagerfanta->getNbResults() / $pagerfanta->getMaxPerPage());
      $pagerfanta->setCurrentPage(min($page, $maxPages));
      
  4. Doctrine Version Mismatch

    • Issue: Incompatible Doctrine Collections versions may break the adapter.
    • Fix: Pin versions in composer.json:
      "require": {
          "doctrine/collections": "^3.0",
          "pagerfanta/doctrine-collections-adapter": "^1.0"
      }
      
  5. Lazy-Loading Quirks

    • Issue: Doctrine’s lazy-loading may not work as expected with paginated results.
    • Fix: Ensure collections are fully loaded before pagination:
      $collection->matching($criteria)->toArray(); // Force load
      

Debugging Tips

  1. Check Collection Structure Use var_dump($collection->getIterator()->current()) to verify data integrity.

  2. Log Pagerfanta Metadata

    \Log::info('Pagination Meta', [
        'total' => $pagerfanta->getNbResults(),
        'pages' => $pagerfanta->getNbPages(),
        'current' => $pagerfanta->getCurrentPage(),
    ]);
    
  3. Memory Profiling Use Laravel Telescope or Xdebug to monitor memory usage during pagination.

Extension Points

  1. Custom Adapter Logic Extend DoctrineCollectionAdapter for custom behavior:

    class CustomDoctrineCollectionAdapter extends DoctrineCollectionAdapter
    {
        public function getSlice($offset, $length)
        {
            // Custom logic for slicing
            return parent::getSlice($offset, $length);
        }
    }
    
  2. Integrate with Laravel’s Pagination Facade Create a facade to unify Pagerfanta and Laravel’s pagination:

    Facades\Pagination::doctrine($collection, $page, $perPage);
    
  3. Add Twig Extensions Register Pagerfanta helpers in Twig:

    $twig->addFunction(new \Twig\TwigFunction('pagerfanta_links', function ($pagerfanta) {
        return $pagerfanta->getLinks('bootstrap_4');
    }));
    
  4. Event Listeners Trigger events for pagination (e.g., logging, analytics):

    $pagerfanta->addListener('postInitialize', function () {
        \Log::info('Pagerfanta initialized');
    });
    

Configuration Quirks

  1. Default Values Pagerfanta defaults to maxPerPage=10 and currentPage=1. Override explicitly:

    $pagerfanta->setMaxPerPage(25);
    $pagerfanta->setCurrentPage($request->page ?? 1);
    
  2. Case Sensitivity Doctrine Collection methods (e.g., getIterator()) are case-sensitive. Ensure correct usage.

  3. Thread Safety Pagerfanta instances are **not thread

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.
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor
spatie/laravel-javascript-views