Apply auto filters to Eloquent models.
Using this package, easily apply filters, sorting and pagination to Eloquent models and their relations, with query string parameters.
php: ^8.0|^8.1
laravel: >=8.0
For miner php|Laravel versions use other releases.
composer require bahram/bfilters
Your models should use the HasFilter
trait:
use BFilters\Traits;
class MyModel extends Eloquent
{
use HasFilter;
// Add columns which you want to use for "full text serach" in "searchable" or "fillable" array
protected $searchable = [
'first_name',
'last_name'
];
}
php artisan make:filter {name}
for example:
php artisan make:filter UserFilter
use Illuminate\Http\Request;
class UserFilter extends Filter
{
public function __construct(Request $request)
{
parent::__construct($request);
$this->relations = [
//Add the actual name of the relation function that is defined in the original model
'relationName1' => [
'searchName1' => 'Original column1 Name in Relation table',
'searchName2' => 'Original column2 Name in Relation table',
'searchName3' => 'Original column3 Name in Relation table',
//if searchName and original column name is the same :
'Original column4 Name in Relation table'
],
'posts' => [
// in this case when you set posted_at as your filter the filter will applied on 'created_at' field of original table
'posted_at' => 'created_at',
'title',
'topic',
],
];
$this->jsonFields = [
//Add the actual name of the json column
'jsonColumn1' => [
'searchName1' => 'Original field Name 1 in JsonColumn1',
'searchName2' => 'Original field Name 2 in JsonColumn1',
//if searchName and original column name is the same :
'Original field Name 3 in JsonColumn3'
],
];
// set this variabe if you want to have sum of your entries based on a specific column (f.e 'amount')
$this->sumField = 'amount';
// define valid eager loading relations to prevent loading unwanted data
$this->validWiths = ['comments', 'tags'];
}
}
In controllers :
public function index(YourModelFilter $filters): Response
{
[$entries, $count, $sum] = YourModel::filter($filters);
return ($entries->get());
}
In Api Request Query String :
filter:{
"sort":[
{ "field": "created_at", "dir": "asc" },
{ "field": "first_name", "dir": "desc" }
],
"page":{ "limit": 10, "offset": 0 },
"filters":[
//(first_name LIKE '%alireza%' or last_name = '%bahram%') and (mobile LIKE '%9891%')
[
//use "or" for fields in same array & use "and" for fields in different array
{"field": "first_name", "op": "like", "value": "alireza"},
{"field": "last_name", "op": "=", "value": "bahram"}
],
//(mobile LIKE '%9891%')
[
{"field": "mobile", "op": "like", "value": "9891"}
],
[
//full text search : search a string on columns you set in its model "searchable" or "fillable" arrays
{"value" : "al"}
]
],
"with":[
"comments",
"tags"
]
}
public function rules()
{
return [
'id' => 'int|required',
'user_id' => 'exists:users,id'
];
}
In Request
class MessageFilter extends Filter
{
public function __construct(Request $request)
{
$this->relations = [
"packages" => [
"numbers" => function ($query, $filter) {
$query->whereRaw("'{$filter->value}' {$filter->op} ANY(numbers)");
},
],
"line" => [
"line_number" => "number",
],
];
//$this->sumField = null;
$this->validWiths = ["packages"];
parent::__construct($request);
}
}
Assume you have a json column named address like this :
{
"city" : "tehran",
"Street" : "jordan"
}
So you Can simply add Your Json Column(s) to your filter class, like this:
class UserFilter extends Filter
{
public function __construct(Request $request)
{
$this->jsonFields = [
"address" => ["city_name" => "city",
"street_name" => "street
]
];
parent::__construct($request);
}
}
Then you can apply filters on your Model as simple as this :
filter:{"filters":[[{"field":"city_name","op":"=","value":"tehran"}],[{"field":"street_name","op":"=","value":"jordan"}]]}
?filter={"page":{"limit": 10,"offset": 0}}
id
desc) :?filter={"page":{"limit":20,"offset":0},"sort":[{"field":"id","dir":"desc"}]}
?filter={"page":{"limit":20,"offset":0},"sort":[{"field":"id","dir":"desc"}],"filters":[[{"field":"name","op":"like","value":"john"}]]}
or
last name like bahram) and
(email = alib327@gmail.com)?filer={
"page":{"limit":20,"offset":0},
"sort":[{"field":"id","dir":"desc"}],
"filters":[
[
{"field": "first_name", "op": "like", "value": "alireza"},
{"field": "last_name", "op": "=", "value": "bahram"}
],
[
{"field": "email", "op": "=", "value": "09196649497"},
],
]
}
magic filters
as well:without using field
,op
, and value
(email = alib327@gmail.com):
?filer={
"page":{"limit":20,"offset":0},
"sort":[{"field":"id","dir":"desc"}],
"filters":
[
["email","09196649497"],
],
?filer={
"page":{"limit":20,"offset":0},
"sort":[{"field":"id","dir":"desc"}],
"filters":
[
{"value":"alireza"},
],
For example assume a function within your controller:
public function showUserArticles($userId)
{
$filters = new MakeFilter();
$filters->orderBy('posted_at', 'desc');
$filters->addFilter([
[
'field' => 'user_id',
'op' => '=',
'value' => $userId
]
]);
return Http::get(Put your URL here, [
'filter' => $filters->toJson()
]);
}
public function Index(UserFilter $filters)
{
$filters->removeFilter('first_name')->removePagination();
}
$filters->removeFilter('first_name')->removePagination()
->addMagicFilter([
[
'user_id',
$userId
]
]);
$filters->[
'field' => 'posted_at',
'dir' => 'desc'
];
$filters->setFilters([
[
[
'field' => 'user_id',
'op' => '=',
'value' => $userId
],
[
'field' => 'user_name',
'op' => '=',
'value' => $userName
]
]]);
$filters->getFilters();
$filters->getFilter('first_name');
$filters->setWiths(['posts, 'comments']);
$filters->getWiths();
$filters->setPage(
[
"limit" => 20,
"offset"=> 100
]
);
$filters->getPage();