11# Eloquent Criteria Parser
22
3- Using the Eloquent Criteria Parser is quite simple. Just instantiate the class, next, pass a Criteria instance to
4- the ` applyCriteria() ` method along with a ` EloquentQueryBuilder ` instance:
3+ The Eloquent Criteria Parser translates domain Criteria objects into Eloquent query builders with pagination support.
4+
5+ ## Basic Usage
6+
7+ Instantiate the parser and pass a Criteria instance along with an ` EloquentQueryBuilder ` :
58
69``` php
710$parser = new EloquentCriteriaParser();
8- $query = $parser->applyCriteria(User::query(), $criteria);
11+ $result = $parser->applyCriteria(User::query(), $criteria);
912```
1013
11- The returned ` EloquentQueryBuilder ` has the criteria applied. You just need to call the ` get ` method to fetch the data
12- from the database.
14+ The ` applyCriteria() ` method returns an array containing:
15+
16+ - ` builder ` : EloquentQueryBuilder with filters, ordering, and pagination applied
17+ - ` total ` : Total count of records before pagination
18+ - ` page ` : Page value object from the criteria
19+ - ` currentPage ` : Current page number (1-indexed)
1320
1421``` php
15- $users = $query->get();
22+ $items = $result['builder']->get();
23+ $total = $result['total'];
24+ $currentPage = $result['currentPage'];
1625```
1726
18- Alternatively, you can pass an array of strings to map the attributes between the domain and the database.
27+ ## Attribute Mapping
28+
29+ Map domain attributes to database columns by passing an array to the constructor:
1930
2031``` php
2132$parser = new EloquentCriteriaParser([
2233 'domain-attribute' => 'database-attribute',
2334]);
2435```
2536
26- For example,
27- given the following table:
37+ ### Example
38+
39+ Given this users table:
2840
2941``` php
3042$this->builder->create('users', function (Blueprint $table) {
@@ -37,7 +49,7 @@ $this->builder->create('users', function (Blueprint $table) {
3749});
3850```
3951
40- You may use the following configuration to use ` name ` and ` surname ` instead of ` first_name ` and ` last_name ` :
52+ Use ` name ` and ` surname ` in your domain instead of ` first_name ` and ` last_name ` :
4153
4254``` php
4355$parser = new EloquentCriteriaParser([
@@ -46,19 +58,94 @@ $parser = new EloquentCriteriaParser([
4658]);
4759```
4860
49- A criteria search will be something like this:
61+ ## Repository Implementation with PaginatedCollection
62+
63+ The recommended pattern is to use ` PaginatedCollection ` in your repositories:
64+
65+ ``` php
66+ use ComplexHeart\Domain\Criteria\Contracts\PaginatedResult;
67+ use ComplexHeart\Infrastructure\Laravel\Pagination\PaginatedCollection;
68+
69+ class UsersEloquentRepository implements UserRepository
70+ {
71+ private IlluminateCriteriaParser $criteriaParser;
72+
73+ public function __construct()
74+ {
75+ $this->criteriaParser = new EloquentCriteriaParser([
76+ 'name' => 'first_name',
77+ 'surname' => 'last_name'
78+ ]);
79+ }
80+
81+ public function match(Criteria $criteria): PaginatedResult
82+ {
83+ $result = $this->criteriaParser->applyCriteria(User::query(), $criteria);
84+
85+ $items = $result['builder']
86+ ->get()
87+ ->map(fn($row) => UserEntity::fromSource($row))
88+ ->toArray();
89+
90+ return PaginatedCollection::paginate(
91+ items: $items,
92+ total: $result['total'],
93+ perPage: $result['page']->limit(),
94+ currentPage: $result['currentPage'],
95+ );
96+ }
97+ }
98+ ```
99+
100+ ## PaginatedCollection
101+
102+ ` PaginatedCollection ` extends Laravel's ` Collection ` and implements the ` PaginatedResult ` interface from php-criteria.
103+
104+ ### Collection Methods Support
105+
106+ You can use all Laravel Collection methods:
107+
108+ ``` php
109+ $result = $repository->match($criteria);
110+
111+ // Standard Collection methods
112+ $names = $result->map(fn($user) => $user->name)->toArray();
113+ $emails = $result->pluck('email')->toArray();
114+ $filtered = $result->filter(fn($user) => $user->isActive);
115+ ```
116+
117+ ### Pagination Metadata
118+
119+ Access pagination information through these methods:
120+
121+ ``` php
122+ $result->items(); // Get current page items as array
123+ $result->total(); // Total records across all pages
124+ $result->perPage(); // Items per page
125+ $result->currentPage(); // Current page number (1-indexed)
126+ $result->lastPage(); // Last page number
127+ $result->hasMorePages(); // Check if more pages exist
128+ $result->isEmpty(); // Check if current page is empty
129+ $result->isNotEmpty(); // Check if current page has items
130+ $result->count(); // Count items on current page
131+ ```
132+
133+ ### Example Usage
50134
51135``` php
52136$criteria = Criteria::default()
53137 ->withFilterGroup(FilterGroup::create()
54- ->addFilterEqual('name', 'Vicent'));
138+ ->addFilterEqual('name', 'Vincent'))
139+ ->withPageNumber(1, 25);
55140
56- $builder = User::query( );
141+ $result = $repository->match($criteria );
57142
58- $parser = new EloquentCriteriaParser();
59- $users = $parser
60- ->applyCriteria($builder, $criteria)
61- ->get();
62- ```
143+ if ($result->isNotEmpty()) {
144+ echo "Page {$result->currentPage()} of {$result->lastPage()}";
145+ echo "Showing {$result->count()} of {$result->total()} users";
63146
64- This is useful to expose different attributes from different interfaces as HTTP, or CLI.
147+ foreach ($result as $user) {
148+ echo $user->name;
149+ }
150+ }
151+ ```
0 commit comments