Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
Pageable
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
3 / 3
4
100.00% covered (success)
100.00%
1 / 1
 buildPagination
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 buildWithoutPagination
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 buildWithPagination
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace DevToolbelt\LaravelFastCrud\Traits;
6
7use Illuminate\Database\Eloquent\Builder;
8use Illuminate\Database\Eloquent\Model;
9
10/**
11 * Provides pagination functionality for Eloquent queries.
12 *
13 * Supports standard pagination with configurable page size,
14 * and an option to skip pagination entirely for full result sets.
15 *
16 * @example
17 * ```
18 * // Paginated results (default 40 per page)
19 * GET /products
20 *
21 * // Custom page size
22 * GET /products?perPage=20
23 *
24 * // Skip pagination (return all results)
25 * GET /products?skipPagination=true
26 * ```
27 */
28trait Pageable
29{
30    /**
31     * The paginated/fetched data array.
32     *
33     * @var array<int, array<string, mixed>>
34     */
35    protected array $data = [];
36
37    /**
38     * Pagination metadata.
39     *
40     * Contains: current (page), perPage, pagesCount, count (total records)
41     *
42     * @var array{current?: int, perPage?: int, pagesCount?: int, count?: int}
43     */
44    protected array $paginationData = [];
45
46    /**
47     * Builds pagination for the query results.
48     *
49     * @param Builder $query The query builder instance
50     * @param int $perPage Number of items per page (default: 40)
51     * @param string $method Model method to call for serialization (default: 'toArray')
52     */
53    public function buildPagination(Builder $query, int $perPage = 40, string $method = 'toArray'): void
54    {
55        $this->data = [];
56        $this->paginationData = [];
57
58        $request = request();
59
60        if ($request->query('skipPagination')) {
61            $this->buildWithoutPagination($query, $method);
62            return;
63        }
64
65        $this->buildWithPagination($query, $perPage, $method);
66    }
67
68    /**
69     * Fetches all results without pagination.
70     *
71     * @param Builder $query The query builder instance
72     * @param string $method Model method to call for serialization
73     */
74    private function buildWithoutPagination(Builder $query, string $method): void
75    {
76        $query->get()->each(function (Model $row) use ($method): void {
77            $this->data[] = $row->$method();
78        });
79    }
80
81    /**
82     * Fetches paginated results with metadata.
83     *
84     * @param Builder $query The query builder instance
85     * @param int $perPage Number of items per page
86     * @param string $method Model method to call for serialization
87     */
88    private function buildWithPagination(Builder $query, int $perPage, string $method): void
89    {
90        $count = $query->count();
91        $paginate = $query->paginate($perPage);
92
93        $this->data = array_map(
94            static fn(Model $model): array => $model->$method(),
95            $paginate->items()
96        );
97
98        $this->paginationData = [
99            'current' => $paginate->currentPage(),
100            'perPage' => $paginate->perPage(),
101            'pagesCount' => (int) ceil($count / $paginate->perPage()),
102            'count' => $count,
103        ];
104    }
105}