市面上常见的php框架有不少,最近由于有技术需求,因此对常见的php框架的中间件进行了一些了解。各个框架尽管在目标上对php框架的定义大同小异,可是在实现方式上却各有不一样,且看下文:php
首先什么是php的中间件?nginx
根据zend-framework中的定义:git
所谓中间件是指提供在请求和响应之间的,可以截获请求,并在其基础上进行逻辑处理,与此同时可以完成请求的响应或传递到下一个中间件的代码。github
这一介绍十分的简洁,但却略显抽象,接下来咱们经过例子来一个个看。api
首先来看CI框架,php star数 12830.
做为一款很是简洁的框架,CI被吐槽的很多,可是也有不少人喜欢。首先来看它官方给出的一张请求时序图:跨域
根据上文中对中间件的定义,那么对于CI框架来讲,惟一称得上是内置中间件的:Security模块浏览器
Security模块是在请求进入controller以前实现的逻辑:缓存
乍看起来,CI框架的中间件十分的局限,可是其实它却提供了无限的可能性。。由于CI中还提供了一个叫作Hooks的功能。即钩子。php框架
下面来看两个个hooks的例子:安全
定义一个在controller逻辑以前的钩子,并指定钩子的参数、类名或函数名信息:
$hook['pre_controller'] = array( 'class' => 'MyClass', 'function' => 'Myfunction', 'filename' => 'Myclass.php', 'filepath' => 'hooks', 'params' => array('beer', 'wine', 'snacks') );
定义一个在controller逻辑以后的钩子,并直接给出其实现:
$hook['post_controller'] = function() { /* do something here */ };
为何说CI没提供什么像样的中间件可是又很灵活呢,就是由于它能够在以下的多个阶段进行挂钩子的操做。细数过来有7种之多。
从后文中能够看出,不少其余的框架可能也就会涵盖两三种阶段,所以,从这个角度上来讲,CI的钩子组合而成的中间件的确很灵活。
$this->CI =& get_instance()
方法来获取 CI 超级对象,以及使用 $this->CI->output->get_output()
方法来 获取最终的显示数据;总结来看,CI中的中间件:
github star 24997
做为最近两年大红大紫的Laravel,的确也是有必要对其中间件机制进行了解:
首先Laravel提供了一个很好的中间件自动生成工具:php artisan make:middleware OldMiddleware
由Laravel的命令行完成,这种看似简单的命令行工具其实能够对框架的扩展起到很是重要的做用。
再来看一个Laravel中典型的请求过滤器:
<?php namespace App\Http\Middleware; use Closure; class OldMiddleware { /** * 运行请求过滤器。 * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { if ($request->input('age') <= 200) { return redirect('home'); } return $next($request); } }
过滤器,filter,是中间件中使用最普遍的一种,不少框架里甚至filter就等同于中间件。意如其名,便是对请求Request进行某种过滤,这个过滤能够是参数上的限制、安全策略的限制、http协议的限制,只要是请求中带来的属性,均可以据此进行过滤。
同时这里也能够看到,Laravel使用闭包的方式进行请求的传递,真正践行的优雅的中间件串联的方式,只须要调用next函数,请求便可被按照预先定义的规则传递到下一个中间件中。
Laravel支持全局的中间件和根据具体路由规定的中间件两种,同时优先级又以定义顺序为准。作到全局与具体状况的兼顾。同时它显示的支持前置、后置和Terminable三种中间件,覆盖了大部分的中间件场景,是一种相对不错的设计。
但美中不足或者说场景覆盖不够友好的地方在于它以路由的方式组织中间件,会与controller有些脱节,每次定义controller中action行为的时候,还须要转换为路由进行配置,略有些不方便。
总结来看
github star 4668
yii框架首先是中国人开发的,star数虽然不是不少,可是功能也算丰富。
yii框架从1.1到2.0,通过了一个比较大的升级,支持了不少新的特性,若是不支持,只怕是要落伍了。
在yii框架1.1中,中间件干脆就叫filters了,十分的直白,分为pre-filter和post-fiter两种,即前文中说的,在进入controller以前的过滤逻辑,和完成controller处理以后的过滤逻辑。
可是到了yii2.0以后,filters通过了一层升级,到了behaviors,明确了一点:重心放在了每个controller的行为上,而不是像Laravel同样controller很傻很单纯。
yii框架的behaviors能够在controller或application中配置。
这里是一个访问控制的filter,具体进行什么样的访问控制由className定义,同时对controller中的action支持“only”关键字,还有“”关键字,可以支持排除法的功能,这个在一些场景下仍是颇有用的。同时“roles”也可以支持你预先定义好的角色的概念,好比学生没法访问教师后台,而教师没法访问学生论坛等。
use yii\filters\AccessControl; public function behaviors() { return [ 'access' => [ 'class' => AccessControl::className(), 'only' => ['create', 'update'], 'rules' => [ // allow authenticated users [ 'allow' => true, 'roles' => ['@'], ], // everything else is denied by default ], ], ]; }
固然,在Yii中你也能够自定义filter:
namespace app\components; use Yii; use yii\base\ActionFilter; class ActionTimeFilter extends ActionFilter { private $_startTime; public function beforeAction($action) { $this->_startTime = microtime(true); return parent::beforeAction($action); } public function afterAction($action, $result) { $time = microtime(true) - $this->_startTime; Yii::trace("Action '{$action->uniqueId}' spent $time second."); return parent::afterAction($action, $result); } }
这里明显能够看出,这个filter针对action,分别在“beforeAction”和“afterAction”两个阶段进行了逻辑处理,完成了请求的计时工做。
因此总的来看,Yii框架中的中间件:
ZendFramework是由zend公司推出的php框架,其目标就是创建一套大而全的php框架。以知足企业应用开发的目标。
ZendFramework由不少不一样的模块构成,使用者能够经过相互组合的方式来实现本身想要的功能,同时也可以不一次加载大而全的框架,十分的灵活。
好比有负责受权的"zend-authentication",或者是负责验证码的"zend-captcha"等等。
其中"zend-stratigility" 负责提供中间件以及中间件执行流的功能。
use Zend\Stratigility\MiddlewarePipe; use Zend\Diactoros\Server; require __DIR__ . '/../vendor/autoload.php'; $app = new MiddlewarePipe(); $server = Server::createServer($app, $_SERVER, $_GET, $_POST, $_COOKIE, $_FILES); // Landing page $app->pipe('/', function ($req, $res, $next) { if (! in_array($req->getUri()->getPath(), ['/', ''], true)) { return $next($req, $res); } return $res->end('Hello world!'); }); // Another page $app->pipe('/foo', function ($req, $res, $next) { return $res->end('FOO!'); }); $server->listen();
这里的代码给出了两个中间件的例子。第一个是落地页,监听了root路径,若是命中了这一路由规则,那么请求会被提早结束,返回给用户“Hello world!”。
而第二个中间件去匹配foo这一路径,模糊匹配的方式,若是命中了,会返回FOO并结束请求。
与Laravel相似,这里一样支持使用next(可调用的变量)的方式将请求继续向下传递。而这里中间件配置的方式也跟Laravel比较像,是统一在一个地方根据路由进行配置的,这样彻底能够按照以下的方式根据不一样的路由定义不一样的中间件处理逻辑:
$app->pipe('/api', $apiMiddleware); $app->pipe('/docs', $apiDocMiddleware); $app->pipe('/files', $filesMiddleware);
总结来看,ZendFramework的中间件:
首先按照不一样的类别列举一下常见的中间件:
因此一个php框架最好可以: