laravellegends/eloquent-filter

一个简单的Eloquent过滤器,用于简化API过滤

3.0.4 2022-07-13 20:43 UTC

This package is auto-updated.

Last update: 2024-08-29 05:07:11 UTC


README

一个有用的库,用于为Eloquent创建过滤器。

此库有助于使用Eloquent在您的Rest API中创建搜索过滤器。

🇧🇷🚀🚀🚀

描述

Eloquent Filter库可用于在Laravel项目中创建模型上的搜索条件模式。想法是简单地将请求负载中的值传递以聚合过滤器。

安装

对于安装,您应该使用Composer。运行以下命令

composer require laravellegends/eloquent-filter

使用指南

可以在将应用搜索过滤器的模型中使用 LaravelLegends\EloquentFilter\Concerns\HasFilter 特性。

use LaravelLegends\EloquentFilter\Concerns\HasFilter;

class User extends Model
{
    use HasFilter;
}

HasFilter 特性提供了 filterwithFilter 方法。

在获取模型结果之前调用 filter 方法是使用此库的简单方法。

示例

class UsersController extends Controller 
{
    use App\Models\User;
    
    public function index()
    {
        return User::filter()->paginate();
    }

    // or

    public function index()
    {
        return User::latest('id')->filter()->paginate();
    }

    // or

    public function index(Request $request)
    {
        return User::filter($request)->paginate();
    }
}

当调用 /api/users?exact[id]=1 时,将显示结果。SQL查询 "select * from users where (id = 1)" 将被应用。

注意:显示 规则 会提供更多信息。

另一种方法是使用特定于模型的过滤器。您可以通过继承ModelFilter类为模型创建自定义过滤器。

为了创建此类,您应该使用以下命令 php artisan make:filter,如下例所示

$ php artisan make:filter UserFilter

上述命令将生成以下类

namespace App\Filters;

use LaravelLegends\EloquentFilter\Filters\ModelFilter;

class UserFilter extends ModelFilter 
{
    public function getFilterables(): array
    {
        return [
            'role_id' => 'not_equal', // or ['not_equal']
            'name'    => ['contains', 'starts_with'],
        ];
    }
}

在控制器中

use App\Models\User;
use Illuminate\Http\Request;
use LaravelLegends\EloquentFilter\Filter;

class UsersController extends Controller
{
    // api/users?starts_with[name]=Wallace&not_equal[role_id]=2

    public function index(Request $request)
    {
        return User::withFilter(new UserFilter, $request)
                    ->orderBy('name')
                    ->get();
    }
}

上述代码将内部调用如下示例

User::where(function ($query) {
    $query->where('name', 'LIKE', 'Wallace%');
    $query->where('role_id', '<>', '2');
})
->orderBy('name')
->get();

它做什么?

此库内部根据具有特殊关键字名称的查询字符串参数应用过滤器。

以下参数列表

max

列的最大值。URL api/users?max[field]=100 等同于 User::where('field', '<=', 100)

min

列的最小值。URL api/users?min[age]=33 等同于 User::where('age', '>=', 33)

contains

包含在列中的搜索词。URL api/users?contains[name]=wallace 等同于 User::where('name', 'LIKE', '%wallace%')

ends_with

根据字符串的结尾内容搜索值。类似于具有 %$value 值的 LIKE

starts_with

当值以特定值开始时筛选字段。URL api/users?starts_with[name]=brcontainer 看起来像 User::where('name', 'LIKE', 'brcontainer%')

exact

通过字段的精确值进行搜索。URL api/users?exact[email]=teste@teste.com 看起来像 User::where('name', '=', 'teste@teste.com')

has

通过关系进行筛选。您可以使用 01 值。

示例

URL api/users?has[posts]=1 等同于 User::has('posts')

URL api/users?has[posts]=0 等同于 User::doesntHave('posts')

is_null

WHERE IS NULLWHERE IS NOT NULL 应用到查询中。

示例

URL api/users?is_null[cpf]=1 等同于 User::whereNull('cpf')

URL api/users?is_null[age]=0 等同于 User::whereNotNull('age')

not_in

当列没有传递的值时进行搜索。

示例

URL api/users?not_in[role][]=1&not_in[role][]=2 等同于 User::whereNotIn('role', [1, 2])

注意:当 not_in[my_field] 是空数组时,不会采取任何操作。

in

当列包含传递的值时进行搜索。

示例

URL api/users?in[role][]=10&in[role][]=20 类似于 User::whereIn('role', [10, 20])

注意:当 in[my_field] 是一个空数组时,不会执行任何操作。

date_max

按日期字段的最高值进行搜索。

URL api/users?date_max[created_at]=2021-01-01 类似于 User::whereDate('created_at', '<=', '2021-01-01')

date_min

按日期字段的最小值进行搜索。

示例

URL api/users?date_min[created_at]=2021-01-01 类似于 User::whereDate('created_at', '>=', '2021-01-01')

not_equal

按不等于传递的值进行搜索。如果你在相关字段中使用,将会应用 whereDoesntHave。

示例

URL api/users?not_equal[profile_id]=3 类似于

User::where('profile_id', '<>', '3');

URL api/users?not_equal[roles.id]=1 类似于

User::whereDoesntHave('roles', fn ($query) => $query->where('id', '=', 3));

year_max

URL api/users?year_max[created_at]=2000 类似于

User::whereYear('created_at', '<=', 2000);

year_min

URL api/users?year_min[created_at]=1998 类似于

User::whereYear('created_at', '>=', 1998);

year_exact

URL api/users?year_exact[created_at]=1998 类似于

User::whereYear('created_at', '=', 1998);

过滤关联字段

你可以在模型中定义的关联方法中应用搜索过滤器。

例如

模型

class User extends Model
{
    use HasFilter;

    public function phones()
    {
        return $this->hasMany(Phone::class, 'user_id');
    }
}

过滤器

class UserFilter extends ModelFilter
{
    public function getFilterables(): array
    {
        return [
            'id'            => ['exact', 'not_equal'],
            'created_at'    => ['year_exact', 'date_max', 'date_min'],
            'phones.number' => ['contains'],
            // or
            'phones'        => new PhoneFilter,
        ];
    }
}

class PhoneFilter extends ModelFilter
{

    public function getFilterables(): array
    {
        return [
            'number' => 'contains'
        ];
    }
}
class UserController extends Controller
{
    public function index()
    {
        // api/users?not_in[role_id][]=1&not_in[role_id][]=3
        
        // select * from users where (role_id NOT IN (1, 3))

        return User::withFilter(new UserFilter)->paginate();
    }

    // Or, apply filter as nested query

    public function index() 
    {

        // api/users?exact[role_id]=1
        
        // select * from users where (role_id = 1)

        return User::where(UserFilter::toClosure())->paginate();
    }

    // Or apply in your query as base condition

    public function index()
    {
        
        // api/users?exact[role_id]=1
        
        // select * from users where role_id = 1

        return User::tap(UserFilter::toClosure())->paginate();
    }
}

在以下示例中,将根据包含值 55 的相关电话过滤用户。

api/users?exact[phones.number]=55 类似于

User::where(function ($query) {
    $query->whereHas('phones', function ($query) {
        $query->where('number', '=', '55');
    });
})->paginate();

Axios 示例

如果你使用 axios 库,你可以使用 params 选项来包含上述过滤器。

示例

const api = axios.create({
    baseURL: 'http://localhost:8000/api'
});

api.get('users', {
    params: { 
        'in[role]' : [1, 2, 3],
        'contains[name]' : 'Maxters',
        'is_null[name]' : 0
    }
})