Skip to content

Commit

Permalink
Implement custom filters and refactor core components
Browse files Browse the repository at this point in the history
This commit introduces custom filtering capabilities and includes several improvements:

- Add support for custom filters in the Filterable trait
- Create MakeCustomFilterCommand for generating custom filter classes
- Refactor FiltersBuilder for better performance and maintainability
- Move FiltererServiceProvider to Providers namespace
- Enhance error handling and type checks throughout the package
- Update README with custom filter documentation and examples
- Add tests for new custom filter functionality
  • Loading branch information
iraklisg committed Oct 8, 2024
1 parent 05cc7b4 commit d344086
Show file tree
Hide file tree
Showing 13 changed files with 421 additions and 77 deletions.
128 changes: 115 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@

This package provides an easy way to add **filtering**, **sorting** and **paging** functionality to Eloquent models.

## Installation
# Installation

Via [Composer](https://getcomposer.org):

``` bash
$ composer require culturegr/filterer
```

## Usage
# Usage

Assume the follwing database scheme:

Expand Down Expand Up @@ -53,7 +53,7 @@ class Client extends Model

> **IMPORTANT** Filterer package strongly relies on Laravel conventions for naming the relationships between models. Therefore, in order for the package to work as expected, the defined **model relationships should be named according to these convantions**
### Using the Trait
## Using the Trait

Filtering, sorting and paging functionality can be added to the `Client` model by using the `Filterable` trait provided by Filterer package:

Expand All @@ -72,7 +72,7 @@ class Client extends Model
}
```

### Defining filterable and sortable fields
## Defining filterable and sortable fields

Fields that can be filtered and/or sorted must be explicitly defined using, respectively, the `fiterable` and `sortable` properties on the model. Both filterable and sortable fields may exist on the model itself or on its first-level relationships:
- Fields that exist on the model itself are defined using the name of the column, i.e `columnName`
Expand All @@ -99,7 +99,7 @@ class Client extends Model
}
```

### Supported data types and operators for filtering
## Supported data types and operators for filtering

The supported data types and their corresponding operations that can be performed when filtering resources are listed in the following table:

Expand All @@ -110,7 +110,7 @@ The supported data types and their corresponding operations that can be performe
| String (*such as varchar, text etc*) | equal, not_equal, contains |


### Filtering models
## Filtering models

Filtered results can be obtained using the filter method (provided by Filterable trait) and passing an array as an argument that has a filters property which contains a list of desired filters, as shown below:
```php
Expand Down Expand Up @@ -166,7 +166,108 @@ Client::filter([
])->get();
```

### Sorting models
### Custom filters

Filterer now supports custom filters, allowing you to define complex or specific filtering logic for your models.

#### Creating a Custom Filter

Use the artisan command to generate a new custom filter:

```bash
php artisan make:custom-filter ActiveClientsFilter
```

This will create a new `ActiveClientsFilter` class in `app/CustomFilters` directory that implements the `CustomFilter` interface.
Then you can define your custom filter logic in the `apply` method.

For example, the following `ActiveClientsFilter` will filters clients who have made an order in the last 30 days.:

```php
<?php

namespace App\CustomFilters;

use CultureGr\Filterer\Contracts\CustomFilterInterface;
use Illuminate\Database\Eloquent\Builder;

class ActiveClientsFilter implements CustomFilterInterface
{
/**
* Apply the custom filter to the query builder.
*
* @param Builder $builder The query builder instance
* @param array<string, mixed> $filter The filter array
*
* @phpstan-param array{
* column: string,
* operator: string,
* query_1: string,
* query_2: string
* } $filter
*/
public function apply(Builder $builder, $filter): Builder
{
// Your custom filter logic here...

$queryValue = $filter['query_1']

if ($queryValue === '1') {
$builder->whereHas('orders', function($q) {
$q->where('created_at', '>=', Carbon::now()->subDays(30));
});
} else {
$builder->where(function($query) {
$query->whereDoesntHave('orders')
->orWhereHas('orders', function($q) {
$q->where('created_at', '<', Carbon::now()->subDays(30));
});
});
}
}
}
```

#### Registering Custom Filters

In your model, add your custom filter to the `$customFilters` array property:

```php
use CultureGr\Filterer\Filterable;
use Illuminate\Database\Eloquent\Model;

class Client extends Model
{
use Filterable;

//...

protected $customFilters = [
'active' => ActiveClientsFilter::class,
];

//...
}
```

#### Using Custom Filters

Now you can use your custom filter in your queries, like you would use any other filter:

```php
Client::filter([
'filters' => [
[
'column' => 'active',
'operator' => 'equals',
'query_1' => '1',
'query_2' => null,
],
],
])->get();
```

## Sorting models

Sorted results can be obtained using the `filter` method and passing an array as an argument that has a `sorts` property which contains a list of desired sorts, as shown below:

Expand Down Expand Up @@ -211,7 +312,7 @@ Client::filter([
])->get();
```

### Paging models
## Paging models

Paginated results can be obtained using the `filterPaginate` method, as shown below:

Expand All @@ -223,7 +324,8 @@ Client::filterPaginate([
> **IMPORTANT:** The `filterPaginate` method always returns an instance of `Illuminate\Pagination\LengthAwarePaginator`. It uses the `limit` from the query string if provided, otherwise it uses the `$defaultLimit` if set, and falls back to a default of 10 if neither is specified.
> By default, the current page is detected by the value of the page query string argument on the HTTP request. This value is automatically detected by Laravel, and is also automatically inserted into links generated by the paginator. For more information on how Laravel handles pagination see [here](https://laravel.com/docs/pagination)
### Combining filtering, sorting and paging
## Combining filtering, sorting and paging

Filtering, sorting and paging functionality can be combined using the `filterPaginate` method provided by `Filterable` trait and passing as an argument an array that contains any three of the `filters`, `sorts` and `limit`/`page` properties:

Expand All @@ -242,7 +344,7 @@ Client::filterPaginate([
]);
```

### Query string format
## Query string format

The argument of the `filter` method can be easily obtained by parsing a query string with the following format:

Expand All @@ -257,17 +359,17 @@ GET http://example.com/clients
&page=<PAGE>
```

## Testing
# Testing

``` bash
$ composer test
```

## License
# License

Please see the [license file](LICENSE.md) for more information.

## Credits
# Credits

- [Code Kerala](https://github.com/codekerala)
- Awesome Laravel/PHP community
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "culturegr/filterer",
"name": "yppo/filterer",
"description": "Add filtering, sorting and paging functionality to Eloquent models.",
"license": "MIT",
"authors": [
Expand Down Expand Up @@ -38,7 +38,7 @@
"extra": {
"laravel": {
"providers": [
"CultureGr\\Filterer\\FiltererServiceProvider"
"CultureGr\\Filterer\\Providers\\FiltererServiceProvider"
]
}
}
Expand Down
49 changes: 49 additions & 0 deletions src/Commands/MakeCustomFilterCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace CultureGr\Filterer\Commands;

use Illuminate\Console\GeneratorCommand;

class MakeCustomFilterCommand extends GeneratorCommand {
/**
* The console command name.
*
* @var string
*/
protected $name = 'make:custom-filter';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Create a new custom filter class';

/**
* The type of class being generated.
*
* @var string
*/
protected $type = 'CustomFilter';

/**
* Get the stub file for the generator.
*
* @return string
*/
protected function getStub()
{
return dirname(__DIR__) . '/stubs/custom-filter.stub';
}

/**
* Get the default namespace for the class.
*
* @param string $rootNamespace
* @return string
*/
protected function getDefaultNamespace($rootNamespace)
{
return $rootNamespace.'\CustomFilters';
}
}
23 changes: 23 additions & 0 deletions src/Contracts/CustomFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace CultureGr\Filterer\Contracts;

use Illuminate\Database\Eloquent\Builder;

interface CustomFilter
{
/**
* Apply the custom filter to the query builder.
*
* @param Builder $builder The query builder instance
* @param array<string, mixed> $filter The filter array
*
* @phpstan-param array{
* column: string,
* operator: string,
* query_1: string,
* query_2: string
* } $filter
*/
public function apply(Builder $builder, array $filter): void;
}
Loading

0 comments on commit d344086

Please sign in to comment.