Uniondrug Middleware 中间件组件
基于Phalcon的uniondrug/framework项目中,增加中间件处理流程的支持。, (*1)
感谢
https://github.com/limingxinleo/x-phalcon-middleware
https://github.com/fastdlabs/middleware, (*2)
安装
$ composer require uniondrug/middleware
使用
修改配置文件,引入中间件组件
在app.php配置文件中增加中间件组件的注册, (*3)
<?php
return [
'default' => [
...
'providers' => [
\Uniondrug\Middleware\MiddlewareServiceProvider::class,
],
...
],
];
添加middlewares.php配置文件,定义中间件, (*4)
<?php
/**
* middleware.php
*
*/
return [
'default' => [
// 应用定义的中间件
'middlewares' => [
'test1' => \App\Middlewares\Test1Middleware::class,
'test2' => \App\Middlewares\Test2Middleware::class,
'test3' => \App\Middlewares\Test3Middleware::class,
'test4' => \App\Middlewares\Test4Middleware::class,
'test5' => \App\Middlewares\Test5Middleware::class,
],
// 全局中间件,会应用在全部路由,优先级在应用定义之前
'global' => [
'cors', 'cache', 'favicon', 'trace',
],
// 全局中间件,会应用在全部路由,优先级在应用定义之后
'globalAfter' => [
'powered',
],
// 以下是中间件用到的配置参数
'cache' => [
'lifetime' => 60,
],
'powered_by' => 'Un',
],
];
开发中间件
创建中间件。中间件必须从Uniondrug\Middleware\Middleware继承。实现handle方法。该方法有两个参数:request是Phalcon的Phalcon\Http\Request对象,next是下一个中间件代理。
在处理过程中,可以直接返回一个Phalcon\Http\Response对象,终止后续的中间件,或者返回下一个中间件代理的处理结果(链式传递)。, (*5)
<?php
/**
* Test1Middleware.php
*
*/
namespace App\Middlewares;
use Phalcon\Http\RequestInterface;
use Uniondrug\Middleware\DelegateInterface;
use Uniondrug\Middleware\Middleware;
class Test1Middleware extends Middleware
{
public function handle(RequestInterface $request, DelegateInterface $next)
{
echo "Test1.0\n";
$response = $next($request);
echo "Test1.1\n";
return $response;
}
}
中间件开发好后,需要在middleware.php配置文件中注册一个别名,在使用过程中以别名调用。, (*6)
使用中间件
中间件在控制器中使用。在控制器中有两种方法定义需要使用哪些中间件。, (*7)
1、在beforeExecuteRoute()方法中配置。, (*8)
通过middlewareManager组件的bind方法,指派对应的中间件。, (*9)
其中第一个参数是控制器本身,, (*10)
第二个参数是一组中间件别名,, (*11)
可选的第三个参数可以指明中间件的绑定范围:
only 指只有在列表中的 action 使用该组中间件
except 指除了列表中的 action 以外的所有方法使用该组中间件
如果only/except都不指定,那么整个控制器的方法都会使用改组中间件, (*12)
2.通过注解的方法定义中间件, (*13)
注解Middleware定义当前控制器或者方法使用的中间别名。可以定义多个。, (*14)
<?php
/**
* IndexController.php
*
*/
namespace App\Controllers;
use Phalcon\Mvc\Controller;
/**
* Class IndexController
*
* @package App\Controllers
* @Middleware('test1')
*/
class IndexController extends Controller
{
public function beforeExecuteRoute($dispatcher)
{
$this->middlewareManager->bind($this, ['test2']);
$this->middlewareManager->bind($this, ['test3'], ['only' => ['indexAction']]);
}
/**
* @Middleware('test4', 'test5')
*/
public function indexAction()
{
//var_dump($this->middlewareManager);
return $this->response->setJsonContent(['msg' => memory_get_usage()]);
}
public function showAction()
{
return $this->response->setJsonContent(['msg' => 'show']);
}
}
中间件调用的顺序
- -> 配置文件定义的
global定义的中间件
- ->
bind()方法绑定到控制器上的中间件
- ->
控制器的注解上定义的中间件
- ->
bind()方法绑定到的Action方法上的中间件
- ->
Action方法的注解定义的中间件
- -> 配置文件定义的
globalAfter定义的中间件
bind()方法定义超过一个中间件时,从后到先倒序执行。, (*15)
比如上面例子里面的indexAction被调用时,中间件的执行顺序是:, (*16)
前置调用:, (*17)
- test2 -> test1 -> test3 -> test4 -> test5
后置调用, (*18)
- test5 -> test4 -> test3 -> test1 -> test2
前置调用 & 后置调用
NOTE:Phalcon的Request对象不同于Psr的HttpRequest对象,它只是PHP原生超全局变量$_GET/$_POST/$_SERVER/$_REQUEST的封装,所以如果想在Middleware中对请求对象进行
改写并且让他影响后续使用,那么直接操作超全局变量。, (*19)
class Test1Middleware extends Middleware
{
public function handle(RequestInterface $request, DelegateInterface $next)
{
echo "Test1.0\n"; // 在 $next($request) 之前的代码,将在请求被最终Controller::Action处理之前调用
$_POST['added_var'] = 'new value'; // 改写请求参数,往Request中添加一个新的POST参数。
// 这样下一个Middleware乃至Controller::Action中使用 `$request` 对象的 `getPost()` 方法就能获取到新的参数值了。
$response = $next($request);
echo "Test1.1\n"; // 在 $next($request) 之后的代码,将在请求被最终Controller::Action处理之后调用
return $response;
}
}
内置中间件
组件自带了几个实用的中间件,在middleware.php配置文件中增加配置即可使用。, (*20)
-
cors 跨域资源共享
-
trace 跟踪服务
-
cache 缓存中间件,只对GET请求有效
-
powered 增加PoweredBy头
-
favicon 过滤favicon.ico请求