介绍
当我们想返回一个由多个参数过滤的用户列表。如下:
/users?name=er&last_name=&company_id=2&roles[]=1&roles[]=4&roles[]=7&industry=5
$request->all()
返回如下:
[
'name' => 'er',
'last_name' => '',
'company_id' => '2',
'roles' => ['1','4','7'],
'industry' => '5'
]
要按所有参数进行过滤,我们需要编码如下:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\User;
class UserController extends Controller
{
public function index(Request $request)
{
$query = User::where('company_id', $request->input('company_id'));
if ($request->has('last_name'))
{
$query->where('last_name', 'LIKE', '%' . $request->input('last_name') . '%');
}
if ($request->has('name'))
{
$query->where(function ($q) use ($request)
{
return $q->where('first_name', 'LIKE', $request->input('name') . '%')
->orWhere('last_name', 'LIKE', '%' . $request->input('name') . '%');
});
}
$query->whereHas('roles', function ($q) use ($request)
{
return $q->whereIn('id', $request->input('roles'));
})
->whereHas('clients', function ($q) use ($request)
{
return $q->whereHas('industry_id', $request->input('industry'));
});
return $query->get();
}
}
使用 Eloquent Filters 写法如下:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\User;
class UserController extends Controller
{
public function index(Request $request)
{
return User::filter($request->all())->get();
}
}
配置
安装
composer require tucker-eric/eloquentfilter
定义一个模型过滤器有以下几种方法:
- 使用 Eloquent Filter 的默认设置
- 对所有过滤器使用自定义命名空间
- 定义模型的默认过滤器
- 动态选择模型的过滤器
默认设置
所有过滤器的默认命名空间都是 App\ModelFilters\
,并且每个 Model 都希望过滤器类名遵循 {$ModelName}Filter
命名规范,而不管模型所在的空间。以下是模型以及各自基于默认命名规范的过滤器示例。
模型 | ModelFilter |
---|---|
AppUser | AppModelFiltersUserFilter |
AppFrontEndPrivatePost | AppModelFiltersPrivatePostFilter |
AppFrontEndPublicGuestPost | AppModelFiltersGuestPostFilter |
Laravel
使用配置文件(可选)
注册服务提供者(Service Provider)后,您可以使用
php artisan model:filter {model}
命令,并允许发布您的配置文件。注册服务提供者不是必须的,只有在您想要更改默认命名空间或使用 artisan 命令时才需要。
安装 Eloquent Fiter 包后,在 config/app.php
配置文件中添加 EloquentFilter\ServiceProvider::class
' providers ' => [
//其他服务提供者......
EloquentFilter \ ServiceProvider :: class
],
使用 publish 命令将配置文件发布到本地配置:
php artisan vendor:publish --provider="EloquentFilter\ServiceProvider"
修改 config/eloquentfilter.php
文件,设置您的模型过滤器命名空间:
'namespace' => "App\\ModelFilters\\",
Lumen
注册服务提供者(可选)
仅在您要使用该php artisan model:filter命令时才需要此选项。
修改 bootstrap/app.php
:
$app->register(EloquentFilter\LumenServiceProvider::class);
修改默认的命名空间,修改 bootstrap/app.php
:
config(['eloquentfilter.namespace' => "App\\Models\\ModelFilters\\"]);
定义默认的模型过滤器
在您的模型里创建一个 public 属性的方法 modelFilter()
, 然后返回 $this->provideFilter(Your\Model\Filter::class)
。
<?php
namespace App;
use EloquentFilter\Filterable;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
use Filterable;
public function modelFilter()
{
return $this->provideFilter(App\ModelFilters\CustomFilters\CustomUserFilter::class);
}
//User Class
}
动态过滤器
您可以通过传递 filter()
方法的第二个参数来定义一个动态过滤器,动态定义过滤器将优先于为模型定义的任何其他过滤器。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\User;
use App\ModelFilters\Admin\UserFilter as AdminFilter;
use App\ModelFilters\User\UserFilter as BasicUserFilter;
use Auth;
class UserController extends Controller
{
public function index(Request $request)
{
$userFilter = Auth::user()->isAdmin() ? AdminFilter::class : BasicUserFilter::class;
return User::filter($request->all(), $userFilter)->get();
}
}
生成过滤器
仅当您在
config/app.php
中的 providers 数组中注册EloquentFilter\ServiceProvider::class
时才可用
您可以用以下 artisan 命令创建一个模型过滤器:
php artisan model:filter User
此命令将会为您的 User 模型在 app/ModelFilters/UserFilter.php
位置创建过滤器。此命令还支持 psr-4。您只需要确保转义类名中的反斜杠(/)。例如:
php artisan model:filter AdminFilters\\User
此命令将会创建 app/ModelFilters/AdminFilters/UserFilter.php
用法
定义过滤器逻辑
根据要过滤参数驼峰形式定义 传给 filter()
方法来定义逻辑
- 忽略空字符串
- 无论参数是什么,
setup()
方法都将会被调用 - 从参数端删除
_id
以定义方法,因此过滤user_id
将使用user()
方法 - 没有对应过滤方法的参数会被忽略
- 参数对应的值将会被注入方法中
- 所有值都可以通过
$this->input()
方法访问,或者通过键$this->input($key)
访问单个值 - 模型过滤器类中可以访问所有
Eloquent Builder
方法
要为以下输入定义方法:
[
'company_id' => 5,
'name' => 'Tuck',
'mobile_phone' => '888555'
]
做法如下:
use EloquentFilter\ModelFilter;
class UserFilter extends ModelFilter
{
protected $blacklist = ['secretMethod'];
// This will filter 'company_id' OR 'company'
public function company($id)
{
return $this->where('company_id', $id);
}
public function name($name)
{
return $this->where(function($q) use ($name)
{
return $q->where('first_name', 'LIKE', "%$name%")
->orWhere('last_name', 'LIKE', "%$name%");
});
}
public function mobilePhone($phone)
{
return $this->where('mobile_phone', 'LIKE', "$phone%");
}
public function setup()
{
$this->onlyShowDeletedForAdmins();
}
public function onlyShowDeletedForAdmins()
{
if(Auth::user()->isAdmin())
{
$this->withTrashed();
}
}
public function secretMethod($secretParameter)
{
return $this->where('some_column', true);
}
}
注意: 在上面的示例中,如果不想从删除输入参数末尾的
_id
,则可以在过滤器上设置protected $drop_id = false
。这样将允许您拥有company()
过滤器方法和companyId()
过滤器方法。注意: 在上面的示例中,每次调用
filter()
时,setup()
中所有方法都会被调用
黑名单
所有定义在黑名单数组中的方法都不会被过滤。这些方法通常用于过滤器内部逻辑。
blacklistMethod()
和 whitelistMethod()
方法被用于动态黑名单和白名单。
在上面的例子中,数组中即使有 secret_method
,secretMethod()
也不会被调用。要调用此方法,需要动态列入白名单:
Example:
public function setup()
{
if(Auth::user()->isAdmin()) {
$this->whitelistMethod('secretMethod');
}
}
其他过滤方法
Filterable trait
还有以下 query builder 帮助方法:
EqoquentFilter Method | QueryBuilder Equivalent |
---|---|
$this->whereLike($column, $string) | $this->where($column, 'LIKE', '%'.$string.'%') |
$this->whereBeginsWith($column, $string) | $query->where($column, 'LIKE', $string.'%') |
$this->whereEndsWith($column, $string) | $query->where($column, 'LIKE', '%'.$string) |
可以从任何 use Filterable
的模型中调用这些方法。
为一个模型应用过滤器
在任意 Eloquent Model
上实现 EloquentFilter\Filterable trait
<?php
namespace App;
use EloquentFilter\Filterable;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
use Filterable;
//User Class
}
然后你可以在模型上调用 filter()
方法,此方法接收一个要过滤数组:
class UserController extends Controller
{
public function index(Request $request)
{
return User::filter($request->all())->get();
}
}
没有评论