Skip to content

Commit

Permalink
Merge branch 'develop' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
omalizadeh committed Oct 30, 2021
2 parents 0ea2ac1 + 26ac909 commit a40cf2d
Show file tree
Hide file tree
Showing 31 changed files with 2,485 additions and 1,342 deletions.
31 changes: 31 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Tests

on:
push:
branches: [ main,develop ]
pull_request:
branches: [ main,develop ]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Validate composer.json and composer.lock
run: composer validate --strict

- name: Cache Composer packages
id: composer-cache
uses: actions/cache@v2
with:
path: vendor
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-php-
- name: Install dependencies
run: composer install --prefer-dist --no-progress

- name: Execute tests
run: vendor/bin/phpunit
195 changes: 129 additions & 66 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,94 +1,130 @@
[![Latest Stable Version](https://poser.pugx.org/omalizadeh/laravel-query-filter/v)](https://packagist.org/packages/omalizadeh/laravel-query-filter)
[![Tests](https://github.com/omalizadeh/laravel-query-filter/actions/workflows/tests.yml/badge.svg)](https://github.com/omalizadeh/laravel-query-filter/actions/workflows/tests.yml)
[![License](https://poser.pugx.org/omalizadeh/laravel-query-filter/license)](https://packagist.org/packages/omalizadeh/laravel-query-filter)
[![Total Downloads](https://poser.pugx.org/omalizadeh/laravel-query-filter/downloads)](https://packagist.org/packages/omalizadeh/laravel-query-filter)

# Laravel Query Filter
Laravel query filter provides an elegant way to filter resources via request query string.
You can specify conditions in query string to filter eloquent models and resources.

Laravel query filter provides an elegant way to filter resources via request query string. You can specify conditions in
query string to filter eloquent models and resources.

## Installation & Usage

Install via composer:

```
composer require omalizadeh/laravel-query-filter
```

Make a filter class:

```
php artisan make:filter FilterClassName
```

Add trait in model:

```php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Omalizadeh\QueryFilter\Traits\HasFilter;

class Admin extends Model
class User extends Model
{
use HasFilter;

public function profile()
public function profile(): HasOne
{
return $this->hasOne(Profile::class);
}

public function posts()
public function posts(): HasMany
{
return $this->hasMany(Post::class);
}
}
```
Set filterable attributes, relations and other options:

Set filterable attributes, relations and other options in filter class:

```php
<?php

namespace App\Http\Filters;
namespace App\Filters;

use Illuminate\Http\Request;
use Omalizadeh\QueryFilter\Filter;
use Omalizadeh\QueryFilter\ModelFilter;

class AdminFilter extends Filter
class UserFilter extends ModelFilter
{
public function __construct(Request $request)
protected function selectableAttributes(): array
{
parent::__construct($request);
$this->sortableAttributes = [
return [
'id',
'created_at'
'phone'
];
}

protected function sortableAttributes(): array
{
return [
'id',
'created_at',
'updated_at'
];
$this->filterableAttributes = [
'username',
}

protected function summableAttributes(): array
{
return [
'views'
];
}

protected function filterableAttributes(): array
{
return [
'id',
'phone',
'is_active'
];
$this->filterableRelations = [
/* 'relation' => [
* 'attribute1',
* 'attribute2'
* ]
*/
}

protected function filterableRelations(): array
{
return [
'profile' => [
'gender',
'first_name',
'last_name',
'phone',
'email',
'birth_date'
'first_name'
],
'posts' => [
'post_body' => 'body'
]
];
$this->loadableRelations = [
}

protected function loadableRelations(): array
{
return [
'profile'
];
$this->summableAttributes = [
// total sold is a column in admins table
'total_sold'
];
}
}
```
Filtering resources from query string using json formatted filter parameter with pagination & sort:
```json
api/admins?filter={

Filtering resources via json formatted filter parameter with pagination & sort sent as `q` in query string:

```
api/users?q={
"page": {
"limit": 20,
"offset": 0
},
"sort": [
"sorts": [
{
"field": "id",
"dir": "desc"
Expand All @@ -99,73 +135,100 @@ api/admins?filter={
{
"field": "is_active",
"op": "=",
"value": "="
"value": true
}
]
],
"with": ["profile"]
"sums": ["views"],
"withs": ["profile"]
}
```

In Controller:

```php
use App\Http\Filters\AdminFilter;

public function index(AdminFilter $filters)
public function index(UserFilter $userFilter)
{
// count: total resources based on filters
// sum: sum of given attributes in filter if there is any
list($admins, $count, $sum) = Admin::filter($filters);
$admins = $admins->with('posts')->get();
$userFilterResult = User::filter($userFilter);

// total resources based on filters
$count = $userFilterResult->count();

// total sum of given attributes in filter if there is any
$sums = $userFilterResult->sums();

// Get query result as collection
$users = $userFilterResult->data();

// do stuff and return response
}
```

### Available Operators

| Operators | Value | Description |
| --------- | -------------- | ------------------------------------------------------ |
| = | string/numeric | Field is equal to value |
| = | string/numeric/bool | Field is equal to value |
| != | string/numeric/bool | Field is not equal to value |
| <> | string/numeric/bool | Field is not equal to value |
| > | string/numeric | Field is greater than value |
| >= | string/numeric | Field is greater than or equal to value |
| < | string/numeric | Field is lower than value |
| <= | string/numeric | Field is lower than or equal to value |
| != | string/numeric | Field is not equal to value |
| <> | string/numeric | Field is not equal to value |
| like | string | Field is like string value |
| not like | string | Field is not like string |
| in | array | Field value is in given array |
| not | NULL/array | Field is not null (for null value)/ Not in given array |
| is | NULL | Field is null |
| not | null/array | Field is not null (for null value)/ Not in given array |
| is | null | Field is null |

### Query String Format

Example conditions:

```
(`is_active` = 1 OR `username` like "%omalizadeh%") AND (`first_name` like "%omid%")
(`is_active` = 1 OR `phone` like "%912%") AND (`first_name` like "%omid%")
```

Then json filter will be:

```json
{
"page":{"limit":20,"offset":0},
"sort":[
{"field":"id","dir":"desc"}
"page": {
"limit": 20,
"offset": 0
},
"sorts": [
{
"field": "id",
"dir": "desc"
}
],
"filters":[
"filters": [
[
{"field":"is_active","op":"=","value":1},
{"field":"username","op":"like","value":"omalizadeh"},
{
"field": "is_active",
"op": "=",
"value": 1
},
{
"field": "phone",
"op": "like",
"value": "912"
}
],
[
{"field":"first_name","op":"like","value":"omid"},
[
{
"field": "first_name",
"op": "like",
"value": "omid",
"has": true
}
]
],
"sum": [
"total_sold"
]
}
```

## License

Laravel Query Filter is open-sourced software licensed under the [MIT license](LICENSE.md).

## Acknowledgments

This package is based on [Behamin BFilter Package](https://github.com/alirezabahram7/bfilter).
Thanks To [Alireza Bahrami](https://github.com/alirezabahram7) and [Hossein Ebrahimzadeh](https://github.com/Hebrahimzadeh)
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
}
],
"require": {
"php": "^7.3|^8.0",
"php": "^7.4|^8.0",
"ext-json": "*",
"illuminate/contracts": "^6.0|^7.0|^8.0",
"illuminate/console": "^6.0|^7.0|^8.0",
Expand All @@ -45,7 +45,7 @@
"extra": {
"laravel": {
"providers": [
"Omalizadeh\\QueryFilter\\QueryFilterServiceProvider"
"Omalizadeh\\QueryFilter\\Providers\\QueryFilterServiceProvider"
]
}
},
Expand Down
Loading

0 comments on commit a40cf2d

Please sign in to comment.