bahram / bfilters

用于对eloquent模型进行自定义过滤的包

v1.13.2 2024-08-10 09:27 UTC

README

将自动过滤器应用于Eloquent模型。
使用此包,可以轻松地对Eloquent模型及其关系应用过滤器、排序和分页,使用查询字符串参数。

要求

php: ^8.0|^8.1
laravel: >=8.0

对于较旧的php|Laravel版本,请使用其他版本。

安装

composer require bahram/bfilters

在Eloquent模型上使用HasFilter特性

您的模型应使用HasFilter特性

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}

例如

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'];
    }
}

用法

在控制器中

public function index(YourModelFilter $filters): Response
{
    [$entries, $count, $sum] = YourModel::filter($filters);
    return ($entries->get());
}

在API请求查询字符串中

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'
    ];
}

如果您需要在关系上应用自定义过滤器:(例如PostgreSQL中的数组搜索)

在请求中


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);
    }
}

Json搜索

假设您有一个名为address的json列,如下所示

{
"city" : "tehran",
"Street" : "jordan"
}

因此,您可以简单地将您的json列添加到过滤器类中,如下所示

class UserFilter extends Filter
{
    public function __construct(Request $request)
    {
      $this->jsonFields = [
            "address" => ["city_name" => "city",
                            "street_name" => "street
                            ]
        ];

        parent::__construct($request);
    }
}

然后,您可以将过滤器应用于模型,就像这样

filter:{"filters":[[{"field":"city_name","op":"=","value":"tehran"}],[{"field":"street_name","op":"=","value":"jordan"}]]}

查询字符串示例

分页: per_page=10

?filter={"page":{"limit": 10,"offset": 0}}

分页 per_page=20 并且(按 id 降序排列)

?filter={"page":{"limit":20,"offset":0},"sort":[{"field":"id","dir":"desc"}]}

添加一个过滤器:name like john

?filter={"page":{"limit":20,"offset":0},"sort":[{"field":"id","dir":"desc"}],"filters":[[{"field":"name","op":"like","value":"john"}]]}

(first_name like alireza 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"},
                    ],
                   ]
        }
                    

您也可以使用魔法过滤器

无需使用fieldopvalue(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"},
                    ],
                    

##基本方法

使用Make Filter类在API调用上创建自定义过滤器

例如,假设控制器中的一个函数

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();
    }

"addMagicFilter"方法

     $filters->removeFilter('first_name')->removePagination()
                ->addMagicFilter([
                                    [
                                        'user_id',
                                         $userId
                                    ]
                                ]);

"addOrder"方法

$filters->[
                'field' => 'posted_at',
                'dir' => 'desc'
            ];

使用"setFilters"方法设置多个过滤器

    $filters->setFilters([
    [
        [
        'field' => 'user_id',
        'op' => '=',
        'value' => $userId
        ],
        [
        'field' => 'user_name',
        'op' => '=',
        'value' => $userName
        ]
    ]]);

使用"getFilters"方法获取已应用的过滤器数组

$filters->getFilters();

使用"getFilter"方法获取特定过滤器

$filters->getFilter('first_name');

使用"setWiths"方法预加载模型的某些特定关系

$filters->setWiths(['posts, 'comments']);

使用"getWiths"方法获取给定过滤器上已设置的关系

$filters->getWiths();

使用"setPage"方法设置过滤器的分页

$filters->setPage(
                    [
                        "limit" => 20,
                        "offset"=> 100
                    ]
                  );

使用"getPage"方法获取已应用于给定请求的分页

$filters->getPage();