Skip to content

Commit 72b8e3d

Browse files
authored
Merge pull request #26 from karimalihussein/feature/add-range-filters-to-pagination
Add Range Filtering with RangeFromFilter and RangeToFilter for Flexible Query Handling
2 parents 78ab9e6 + 5d236ef commit 72b8e3d

5 files changed

+148
-37
lines changed

README.md

+71-36
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
## A query database collection for use with Laravel Pipeline
32

43
[![Latest Version on Packagist](https://img.shields.io/packagist/v/l3aro/pipeline-query-collection.svg?style=flat-square)](https://packagist.org/packages/l3aro/pipeline-query-collection)
@@ -25,7 +24,7 @@ $users = User::query()
2524
->get();
2625
```
2726

28-
As you all can see, it's obviously that filter conditions will continue to grow as well as the duplication of same filter for other queries. We can use Laravel Pipeline combine with some pre-made queries to refactor this
27+
As you all can see, it's obviously that filter conditions will continue to grow as well as the duplication of same filter for other queries. We can use Laravel Pipeline combine with some pre-made queries to refactor this
2928

3029
```php
3130
use Baro\PipelineQueryCollection;
@@ -42,31 +41,32 @@ $users = Users::query()->filter([
4241

4342
## Table of Contents
4443

45-
* [A query database collection for use with Laravel Pipeline](#a-query-database-collection-for-use-with-laravel-pipeline)
46-
* [Table of Contents](#table-of-contents)
47-
* [Installation](#installation)
48-
* [Usage](#usage)
49-
* [Preparing your model](#preparing-your-model)
50-
* [Feature](#feature)
51-
* [Bitwise filter](#bitwise-filter)
52-
* [Boolean filter](#boolean-filter)
53-
* [Date From filter](#date-from-filter)
54-
* [Date To filter](#date-to-filter)
55-
* [Exact filter](#exact-filter)
56-
* [Relation filter](#relation-filter)
57-
* [Relative filter](#relative-filter)
58-
* [Scope filter](#scope-filter)
59-
* [Trash filter](#trash-filter)
60-
* [Sort](#sort)
61-
* [Detector](#detector)
62-
* [Custom search column](#custom-search-column)
63-
* [Custom search value](#custom-search-value)
64-
* [Extend filter](#extend-filter)
65-
* [Testing](#testing)
66-
* [Contributing](#contributing)
67-
* [Security Vulnerabilities](#security-vulnerabilities)
68-
* [Credits](#credits)
69-
* [License](#license)
44+
- [A query database collection for use with Laravel Pipeline](#a-query-database-collection-for-use-with-laravel-pipeline)
45+
- [Table of Contents](#table-of-contents)
46+
- [Installation](#installation)
47+
- [Usage](#usage)
48+
- [Preparing your model](#preparing-your-model)
49+
- [Feature](#feature)
50+
- [Bitwise filter](#bitwise-filter)
51+
- [Boolean filter](#boolean-filter)
52+
- [Date From filter](#date-from-filter)
53+
- [Range Filter](#range-filter)
54+
- [Date To filter](#date-to-filter)
55+
- [Exact filter](#exact-filter)
56+
- [Relation filter](#relation-filter)
57+
- [Relative filter](#relative-filter)
58+
- [Scope filter](#scope-filter)
59+
- [Trash filter](#trash-filter)
60+
- [Sort](#sort)
61+
- [Detector](#detector)
62+
- [Custom search column](#custom-search-column)
63+
- [Custom search value](#custom-search-value)
64+
- [Extend filter](#extend-filter)
65+
- [Testing](#testing)
66+
- [Contributing](#contributing)
67+
- [Security Vulnerabilities](#security-vulnerabilities)
68+
- [Credits](#credits)
69+
- [License](#license)
7070

7171
## Installation
7272

@@ -99,7 +99,9 @@ return [
9999
```
100100

101101
## Usage
102+
102103
### Preparing your model
104+
103105
To use this collection with a model, you should implement the following interface and trait:
104106

105107
```php
@@ -138,6 +140,7 @@ YourModel::query()->filter([
138140
```
139141

140142
### Feature
143+
141144
Here the use all filter and sort in the collection
142145

143146
#### Bitwise filter
@@ -163,6 +166,7 @@ User::query()->filter([
163166
```
164167

165168
#### Date From filter
169+
166170
```php
167171
use Baro\PipelineQueryCollection\DateFromFilter;
168172
use Baro\PipelineQueryCollection\Enums\MotionEnum;
@@ -176,6 +180,7 @@ User::query()->filter([
176180
```
177181

178182
#### Date To filter
183+
179184
```php
180185
use Baro\PipelineQueryCollection\DateToFilter;
181186
use Baro\PipelineQueryCollection\Enums\MotionEnum;
@@ -188,7 +193,27 @@ User::query()->filter([
188193
]);
189194
```
190195

196+
# Range Filter
197+
198+
```php
199+
use Baro\PipelineQueryCollection\RangeFromFilter;
200+
use Baro\PipelineQueryCollection\RangeToFilter;
201+
202+
// Example: products?price_from=100&price_to=500
203+
Product::query()->filter([
204+
RangeFromFilter::make('price'), // Adds where price >= 100
205+
RangeToFilter::make('price'), // Adds where price <= 500
206+
]);
207+
208+
// Example: clients?age_min=18&age_max=65
209+
Client::query()->filter([
210+
RangeFromFilter::make('age')->setPostFix('min'), // Adds where age >= 18
211+
RangeToFilter::make('age')->setPostFix('max'), // Adds where age <= 65
212+
]);
213+
```
214+
191215
#### Exact filter
216+
192217
```php
193218
use Baro\PipelineQueryCollection\ExactFilter;
194219

@@ -199,6 +224,7 @@ User::query()->filter([
199224
```
200225

201226
#### Relation filter
227+
202228
```php
203229
use Baro\PipelineQueryCollection\RelationFilter;
204230

@@ -223,6 +249,7 @@ User::query()->filter([
223249
```
224250

225251
#### Scope filter
252+
226253
```php
227254
// users?search=Baro
228255

@@ -246,23 +273,26 @@ User::query()->filter([
246273
#### Trash filter
247274

248275
When using Laravel's [soft delete](https://laravel.com/docs/master/eloquent#querying-soft-deleted-models), you can use the pipe `TrashFilter`
249-
to query these models. The default query name is `trashed`, and filters responds to particular values:
250-
* `with`: the query should be `?trashed=with` to include soft deleted records to the result set
251-
* `only`: the query should be `?trashed=only` to return only soft deleted records to the result set
252-
* any other value, or completely remove `trashed` from request query will return only records that are not soft deleted in the result set
276+
to query these models. The default query name is `trashed`, and filters responds to particular values:
253277

254-
You can change query name `trashed` by passing your custom name to the `TrashFilter` constructor
255-
```php
278+
- `with`: the query should be `?trashed=with` to include soft deleted records to the result set
279+
- `only`: the query should be `?trashed=only` to return only soft deleted records to the result set
280+
- any other value, or completely remove `trashed` from request query will return only records that are not soft deleted in the result set
281+
282+
You can change query name `trashed` by passing your custom name to the `TrashFilter` constructor
283+
284+
```php
256285
use Baro\PipelineQueryCollection\TrashFilter;
257286

258287

259288
// ?removed=only
260289
User::query()->filter([
261-
TrashFilter::make('removed'), // where `deleted_at` is not null
290+
TrashFilter::make('removed'), // where `deleted_at` is not null
262291
]);
263292
```
264293

265294
#### Sort
295+
266296
```php
267297
use Baro\PipelineQueryCollection\ScopeFilter;
268298

@@ -273,7 +303,9 @@ User::query()->filter([
273303
```
274304

275305
### Detector
306+
276307
Sometimes, you want to setup your request with a prefix like `filter.`. You can config every pipe that have it
308+
277309
```php
278310
use Baro\PipelineQueryCollection\ExactFilter;
279311

@@ -285,6 +317,7 @@ User::query()->filter([
285317
```
286318

287319
Or, you can define it globally
320+
288321
```php
289322
// users?filter[id]=4&filter[permission][0]=1&filter[permission][1]=4
290323

@@ -319,7 +352,9 @@ User::query()->filter([
319352
RelativeFilter::make('name')->value('Baro'), // where('name', 'like', "%Baro%")
320353
]);
321354
```
355+
322356
### Extend filter
357+
323358
Yeah, you are free to use your own pipe. Take a look at some of my filters. All of them extends `BaseFilter` to have some useful properties and functions.
324359

325360
## Testing
@@ -338,8 +373,8 @@ Please review [our security policy](../../security/policy) on how to report secu
338373

339374
## Credits
340375

341-
- [l3aro](https://github.com/l3aro)
342-
- [All Contributors](../../contributors)
376+
- [l3aro](https://github.com/l3aro)
377+
- [All Contributors](../../contributors)
343378

344379
## License
345380

config/pipeline-query-collection.php

+5-1
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,8 @@
1818

1919
// default motion for date filters, can be 'find' or 'till'
2020
'date_motion' => env('PIPELINE_QUERY_COLLECTION_DATE_MOTION', 'find'),
21-
];
21+
22+
// type of postfix for range filters
23+
'range_from_postfix' => env('PIPELINE_QUERY_COLLECTION_RANGE_FROM_POSTFIX', 'from'),
24+
'range_to_postfix' => env('PIPELINE_QUERY_COLLECTION_RANGE_TO_POSTFIX', 'to'),
25+
];

src/BaseRangeFilter.php

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
namespace Baro\PipelineQueryCollection;
4+
5+
abstract class BaseRangeFilter extends BaseFilter
6+
{
7+
protected ?string $postfix = null;
8+
protected string $operator;
9+
10+
public function __construct($field)
11+
{
12+
parent::__construct();
13+
14+
$this->field = $field;
15+
}
16+
17+
abstract protected function getDefaultPostfix(): string;
18+
19+
protected function apply(): static
20+
{
21+
$searchValue = $this->getSearchValue();
22+
23+
$this->query->where($this->field, $this->operator, $searchValue);
24+
25+
return $this;
26+
}
27+
28+
protected function getFilterName(): string
29+
{
30+
$postfix = $this->getPostfix() ?? $this->getDefaultPostfix();
31+
32+
return "{$this->detector}{$this->field}_{$postfix}";
33+
}
34+
35+
public function setPostfix(string $postfix): self
36+
{
37+
$this->postfix = $postfix;
38+
39+
return $this;
40+
}
41+
42+
private function getPostfix(): ?string
43+
{
44+
return $this->postfix;
45+
}
46+
}

src/RangeFromFilter.php

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Baro\PipelineQueryCollection;
4+
5+
final class RangeFromFilter extends BaseRangeFilter
6+
{
7+
protected string $operator = '>=';
8+
9+
protected function getDefaultPostfix(): string
10+
{
11+
return config('pipeline-query-collection.range_from_postfix');
12+
}
13+
}

src/RangeToFilter.php

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Baro\PipelineQueryCollection;
4+
5+
final class RangeToFilter extends BaseRangeFilter
6+
{
7+
protected string $operator = '<=';
8+
9+
protected function getDefaultPostfix(): string
10+
{
11+
return config('pipeline-query-collection.range_to_postfix');
12+
}
13+
}

0 commit comments

Comments
 (0)