laravel5中对pipeline的理解
2015-12-21 15:01
627 查看
原文地址:laravel5中对pipeline的理解 http://sheefeng.com/laravel5-pipeline/
router中的Pipeline:
ControllerDispatcher中的Pipeline:
pipeline的存在主要是为了处理中间件逻辑.
router中的pipeline主要是首先运行选定某一个match到的route后,执行这个route所对应的的MiddleWare,最后执行这个route所对应的controller操作(在controller操作中,也会涉及到pipeline应用,如下).
ControllerDispatcher中的pipeline主要是运行Controller层面(已经选定了某个route以后)的MiddleWare,然后再最后执行controller中的具体操作($this->call($instance, $route, $method)).
理解pipeline,就要理解洋葱模型,像剥洋葱一样一层一层往里面剥.以下面语句为例:
将容器$this->container注入pipeline,$passable这个变量一直在被传递,middleware数组代表要穿过的层,$destination一般是一个闭包函数,代表最终要执行的动作.
上述语句的含义就是携带着$passable这个变量,穿越层层MiddleWare,然后执行最后的$destination,如下所示:
先看看pipeline的源码:
上面的
是核心步骤,不了解arrayreduce语法的人可以参考:http://php.net/manual/zh/function.array-reduce.php
getInitialSlice()用来生成一个closure来实现$destination中的动作.
getSlice()方法用来构造一个closure来不断的迭代pipes里面的每一个pipe
至于getSlice()方法中为何会向下面这样嵌套两个function,我的理解就是arrayreduce中的第二个参数是一个closure,这个closure只接受两个参数的closure,而我们这里有一个$Passable变量需要不断传递,所以需要在内部再加一层function嵌套.
pipeline在laravel中的应用
Router和ControllerDispatcher中都用到了pipeline结构,具体如下所示:router中的Pipeline:
/** * Run the given route within a Stack "onion" instance. * * @param \Illuminate\Routing\Route $route * @param \Illuminate\Http\Request $request * @return mixed */ protected function runRouteWithinStack(Route $route, Request $request) { $middleware = $this->gatherRouteMiddlewares($route); return (new Pipeline($this->container)) ->send($request) ->through($middleware) ->then(function($request) use ($route) { return $this->prepareResponse( $request, $route->run($request) ); }); }
ControllerDispatcher中的Pipeline:
/** * Call the given controller instance method. * * @param \Illuminate\Routing\Controller $instance * @param \Illuminate\Routing\Route $route * @param \Illuminate\Http\Request $request * @param string $method * @return mixed */ protected function callWithinStack($instance, $route, $request, $method) { $middleware = $this->getMiddleware($instance, $method); // Here we will make a stack onion instance to execute this request in, which gives // us the ability to define middlewares on controllers. We will return the given // response back out so that "after" filters can be run after the middlewares. return (new Pipeline($this->container)) ->send($request) ->through($middleware) ->then(function($request) use ($instance, $route, $method) { return $this->call($instance, $route, $method); }); }
pipeline的存在主要是为了处理中间件逻辑.
router中的pipeline主要是首先运行选定某一个match到的route后,执行这个route所对应的的MiddleWare,最后执行这个route所对应的controller操作(在controller操作中,也会涉及到pipeline应用,如下).
ControllerDispatcher中的pipeline主要是运行Controller层面(已经选定了某个route以后)的MiddleWare,然后再最后执行controller中的具体操作($this->call($instance, $route, $method)).
理解pipeline,就要理解洋葱模型,像剥洋葱一样一层一层往里面剥.以下面语句为例:
(new Pipeline($this->container)) ->send($passable) ->through($middleware) ->then($destination);
将容器$this->container注入pipeline,$passable这个变量一直在被传递,middleware数组代表要穿过的层,$destination一般是一个闭包函数,代表最终要执行的动作.
上述语句的含义就是携带着$passable这个变量,穿越层层MiddleWare,然后执行最后的$destination,如下所示:
pipeline的基本原理
下面再来看看pipeline的基本原理:先看看pipeline的源码:
<?php namespace Illuminate\Pipeline; use Closure; use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Pipeline\Pipeline as PipelineContract; class Pipeline implements PipelineContract { /** * The container implementation. * * @var \Illuminate\Contracts\Container\Container */ protected $container; /** * The object being passed through the pipeline. * * @var mixed */ protected $passable; //要在洋葱模型中传递的变量,可以是一个Request对象 /** * The array of class pipes. * * @var array */ protected $pipes = array(); //在洋葱模型中要经过的管道,一般是一些MiddleWare /** * The method to call on each pipe. * * @var string */ protected $method = 'handle'; /** * Create a new class instance. * * @param \Illuminate\Contracts\Container\Container $container * @return void */ public function __construct(Container $container) { $this->container = $container; } /** * Set the object being sent through the pipeline. * * @param mixed $passable * @return $this */ public function send($passable) { $this->passable = $passable; return $this; } /** * Set the array of pipes. * * @param dynamic|array $pipes * @return $this */ public function through($pipes) { $this->pipes = is_array($pipes) ? $pipes : func_get_args(); return $this; } /** * Set the method to call on the pipes. * * @param string $method * @return $this */ public function via($method) { $this->method = $method; return $this; } /** * Run the pipeline with a final destination callback. * * @param \Closure $destination * @return mixed */ public function then(Closure $destination) { $firstSlice = $this->getInitialSlice($destination); //将passable变量和destination这个闭包结合起来,生成一个新的闭包为firstSlice $pipes = array_reverse($this->pipes); return call_user_func( array_reduce($pipes, $this->getSlice(), $firstSlice), $this->passable ); //核心步骤 } /** * Get a Closure that represents a slice of the application onion. * * @return \Closure */ protected function getSlice() { return function($stack, $pipe) { return function($passable) use ($stack, $pipe) { // If the pipe is an instance of a Closure, we will just call it directly but // otherwise we'll resolve the pipes out of the container and call it with // the appropriate method and arguments, returning the results back out. if ($pipe instanceof Closure) { return call_user_func($pipe, $passable, $stack); } else { return $this->container->make($pipe) ->{$this->method}($passable, $stack); } }; }; } /** * Get the initial slice to begin the stack call. * * @param \Closure $destination * @return \Closure */ //getInitialSlice()用来生成一个closure来实现$destination中的动作. protected function getInitialSlice(Closure $destination) { return function($passable) use ($destination) { return call_user_func($destination, $passable); }; } }
上面的
return call_user_func( array_reduce($pipes, $this->getSlice(), $firstSlice), $this->passable );
是核心步骤,不了解arrayreduce语法的人可以参考:http://php.net/manual/zh/function.array-reduce.php
getInitialSlice()用来生成一个closure来实现$destination中的动作.
getSlice()方法用来构造一个closure来不断的迭代pipes里面的每一个pipe
至于getSlice()方法中为何会向下面这样嵌套两个function,我的理解就是arrayreduce中的第二个参数是一个closure,这个closure只接受两个参数的closure,而我们这里有一个$Passable变量需要不断传递,所以需要在内部再加一层function嵌套.
return function($stack, $pipe) { return function($passable) use ($stack, $pipe) { /**中间内容忽略 }; }; }
相关文章推荐
- Windows搭建SMTP邮件服务器
- PHP mail详细示例
- php获取服务器端ip地址
- php curl
- 如何知道tp和panel是哪个厂商
- 高性能PHP框架Yaf框架的安装
- phpstorm安装
- php session 读写锁
- Live555通过SDP文本信息实现对RTP的接收
- yii的部署
- c/s程序版本自动升级的问题,如何判断client端版本号是否最新,然后从指定ftp服务器down
- symfony2项目访问app_dev.php不显示debug工具栏的问题
- PHP草根论之设计模式-訪问者模式
- php 添加curl 模块
- PHP学习日记
- PHP5.3的编译扩展
- YII配置mysql读写分离
- 高负载PHP调优
- Jenkins进阶系列之——06FTP publisher plugin插件下载(支持绝对路径)
- Jenkins进阶系列之——05FTP publisher plugin插件