-
Notifications
You must be signed in to change notification settings - Fork 2
过滤器
Alex edited this page Aug 28, 2019
·
2 revisions
Fluff 的路由只提供了简单匹配机制,如果你想添加过滤条件,可以使用过滤器 (Filter). 过滤器是一个可调用对象,通过给定的参数决定请求是否匹配。过滤器有两种方案:预先注册的过滤器和直接使用的过滤器对象:
use Psr\Http\Message\ServerRequestInterface;
NumericFilter
{
public function __invoke(ServerRequestInterface $serverRequest, array $options, $params)
{
foreach ($options as $option) {
if (!is_numeric($params[$option])) {
return false;
}
}
return true;
}
}
$app->withFilter('numeric', new NumericFilter());
Filter 必须是一个可调动对象,可以预先注册的 Filter 接受三个参数:
- $serverRequest: server-side request 对象。
- $options: 在路由中传入的选项,与 filter 的注册名称相对应。
- $params: 获取到的 URL 参数。
在路由中使用 Filter:
$app->get('/user/{id}', 'userController', [
'filters' => [
'numeric' => ['id',] // `name => options`
]
]);
Application 会在 pattern 匹配成功后,直接调用各个 Filter,当 Filter 返回 true 时匹配成功。返回 false 匹配失败,并且会抛出 ConstanzeStandard\Fluff\Exception\NotFoundException
异常。
过滤器对象也可以直接传入路由的 filters 的选项中:
NumericFilter
{
public function __construct(array $options)
{
$this->options = $options;
}
public function __invoke(ServerRequestInterface $serverRequest, $params)
{
foreach ($this->options as $option) {
if (!is_numeric($params[$option])) {
return false;
}
}
return true;
}
}
$app->get('/user/{id}', 'userController', [
'filters' => [
new NumericFilter(['id'])
]
]);
如果你选择直接传入 filter 对象,Application 就无法拿到 options 数据了,但你可以将 options 以参数的形式直接传入 filter 对象中。
当我们开启路由缓存,并选择直接向 filters 字段传入过滤器对象(方案二)时,必须在过滤器中实现 __set_state
魔术方法。而且必须明确一个事实:闭包是无法被序列化的,也就是说,如果你想使用缓存,就不能直接传入闭包对象,但可以使用 withFilter 方法先将闭包注册进 Application 中(我觉得直接传入闭包的意义也不是很大,因为没有位置给你传递过滤器选项(options))。
NumericFilter
{
public function __construct(array $options)
{
$this->options = $options;
}
public function __invoke(ServerRequestInterface $serverRequest, $params)
{
foreach ($this->options as $option) {
if (!is_numeric($params[$option])) {
return false;
}
}
return true;
}
/**
* 必须实现 __set_state 方法才能使用路由缓存
*/
public function __set_state($array)
{
return new static($array['options']);
}
}