从上一篇我们就大概就知道过滤器的定义和怎样去配置,这一节来说说执行流程 

public function run($handlerAdapter = null) {$handlerAdapter !== null && $this->handlerAdapter = $handlerAdapter;$module = $this->getModules();$handlerPath = $module['controller-path'] . '.' . ucfirst($this->handlerAdapter->getController()) . $module['controller-suffix'];$className = Wind::import($handlerPath);if (!class_exists($className)) throw new WindException('Your requested \'' . $handlerPath . '\' was not found on this server.', 404);$handler = new $className();$handler->setDelayAttributes(array('errorMessage' => array('ref' => 'errorMessage'), 'forward' => array('ref' => 'forward')));$handlerAdapter !== null && $this->resolveActionFilters($handler);try {$forward = $handler->doAction($this->handlerAdapter);$this->doDispatch($forward);} catch (WindForwardException $e) {$this->doDispatch($e->getForward());} catch (WindActionException $e) {$this->sendErrorMessage(($e->getError() ? $e->getError() : $e->getMessage()), $e->getCode());} catch (WindException $e) {$this->sendErrorMessage($e->getMessage(), $e->getCode());}}

  要注意的是 handleAdapter这个属性,这个变量到底里面装的是什么呢

我们在控制台看一下把

我这里解释一下把,这里的this是windClassProxy的实例,还记得它是怎样创建的吗,再贴一下这个代码

/*** 解析action过滤链的配置信息* * @param WindSimpleController $handler        * @return void*/protected function resolveActionFilters(&$handler) {if (!$filters = $this->getConfig('filters')) return;/* @var $cache AbstractWindCache */$_filters = array();if ($cache = Wind::getComponent('windCache')) {$_filters = $cache->get('filters');}$_token = $this->handlerAdapter->getModule() . '/' . $this->handlerAdapter->getController() . '/' . $this->handlerAdapter->getAction();if (!isset($_filters[$_token])) {foreach ($filters as $_filter) {if (empty($_filter['class'])) continue;$_pattern = empty($_filter['pattern']) ? '' : $_filter['pattern'];unset($_filter['pattern']);if ($_pattern) {$_pattern = str_replace(array('*', '/'), array('\w*', '\/'), $_pattern);if (in_array($_pattern[0], array('~', '!'))) {$_pattern = substr($_pattern, 1);if (preg_match('/^' . $_pattern . '$/i', $_token)) continue;} else {if (!preg_match('/^' . $_pattern . '$/i', $_token)) continue;}}$_filters[$_token][] = $_filter;}$cache && $cache->set('filters', $_filters);}if (empty($_filters[$_token])) return;/* @var $proxy WindClassProxy */$proxy = WindFactory::createInstance(Wind::import('WIND:filter.proxy.WindClassProxy'));$proxy->registerTargetObject($handler);foreach ($_filters[$_token] as $value) {$proxy->registerEventListener($this->factory->createInstance(Wind::import($value['class']), array($handler->getForward(), $handler->getErrorMessage(), $this->handlerAdapter, $value)), 'doAction');}$handler = $proxy;}

  

关键是这里 

$proxy = WindFactory::createInstance(Wind::import('WIND:filter.proxy.WindClassProxy'));$proxy->registerTargetObject($handler);foreach ($_filters[$_token] as $value) {$proxy->registerEventListener($this->factory->createInstance(Wind::import($value['class']), array($handler->getForward(), $handler->getErrorMessage(), $this->handlerAdapter, $value)), 'doAction');}

  创建一个代理类,然后帮定一个事件,把过滤器作为事件处理其实例化然后等下触发,不知道为什么要这样做,想得不是很明白

好啦,万事俱备,只欠东风拉,看看它是这样运作拉

try {$forward = $handler->doAction($this->handlerAdapter);$this->doDispatch($forward);} catch (WindForwardException $e) {$this->doDispatch($e->getForward());} catch (WindActionException $e) {$this->sendErrorMessage(($e->getError() ? $e->getError() : $e->getMessage()), $e->getCode());} catch (WindException $e) {$this->sendErrorMessage($e->getMessage(), $e->getCode());}

  这里会调用doAction这个方法,但是这个方法在windProxyClass根本找不到的,所以会调用php的魔术方法拉,如下

public function __call($methodName, $args) {$listeners = isset($this->_listener[$methodName]) ? $this->_listener[$methodName] : array();if (empty($listeners)) return call_user_func_array(array($this->_instance, $methodName), $args);$interceptorChain = $this->_getInterceptorChain($methodName);$interceptorChain->addInterceptors($listeners);$interceptorChain->setCallBack(array($this->_getInstance(), $methodName), $args);return call_user_func_array(array($interceptorChain->getHandler(), 'handle'), (array) $args);}

 好啦,高潮来啦,首先要确定一下这个方法有没有绑定一堆的listener,如果没有,就直接地调用算啦,如果有的话,就加入到链条里

这里很有技巧性,看看

 * 拦截器的执行入口* * @param mixed $var=.. 该接口接受任意参数,并将依次传递给拦截器的前置和后置操作* @return mixed 返回拦截链执行的最终结果*/public function handle() {$args = func_get_args();$this->result = call_user_func_array(array($this, 'preHandle'), $args);if ($this->result !== null) {return $this->result;}if (null !== ($handler = $this->interceptorChain->getHandler())) {$this->result = call_user_func_array(array($handler, 'handle'), $args); //执行过滤器的handle方法} else {$this->result = call_user_func_array(array($this->interceptorChain, 'handle'), $args); //如果返回的handle为空的话就执行过滤链的handle的方法,也就是callback,调用控制器阿 }call_user_func_array(array($this, 'postHandle'), $args);return $this->result;}

  

/*** 返回拦截链中的下一个拦截器* * @return WindHandlerInterceptor*/public function getHandler() {if (count($this->_interceptors) <= 1) {return $this;}$handler = next($this->_interceptors);if ($handler === false) {reset($this->_interceptors);return null;}if (method_exists($handler, 'handle')) {$handler->setHandlerInterceptorChain($this); //这里设置有什么用呢,就死为了最后一个调用过滤链的handle方法return $handler;}return $this->getHandler();}

  

/*** 执行callback方法* * @return mixed $var=.. 如果callBack没有被设置则返回null,否则返回回调函数的结果* @throws WindException 如果回调函数调用失败则抛出异常*/public function handle() {reset($this->_interceptors);if ($this->_callBack === null) return null;if (is_string($this->_callBack) && !function_exists($this->_callBack)) {throw new WindException('[filter.WindHandlerInterceptorChain.handle] ' . $this->_callBack, WindException::ERROR_FUNCTION_NOT_EXIST);}$this->_args || $this->_args = func_get_args();return call_user_func_array($this->_callBack, (array) $this->_args);}

  这个是最后执行的,过滤器一个一个执行完了,就执行callback拉 ,有时间画一个图出来会比较容易理解拉 

转载于:https://www.cnblogs.com/simonlu/p/5071590.html

捣蛋phpwind过滤器执行流程相关推荐

  1. Filter过滤器执行流程

    在上一篇博客我们进行了Filter的入门讲解,这里我们讲解Filter的执行流程,从下图可以大致了解到,当客户端发送请求的时候,会经过过滤器,然后才能到我们的servlet,当我们的servlet处理 ...

  2. Filter_细节_执行流程生命周期

    过滤器执行流程     1. 执行过滤器     2. 执行放行后的资源     3. 回来执行过滤器放行代码下边的代码 过滤器生命周期方法     1. init:在服务器启动后,会创建Filter ...

  3. 捣蛋phpwind之WindFrameWork

    一直都有关注phpwind这个开源产品,从9.0开始就好关注拉,因为官方说把之前的代码重写了一遍,融入了windFramework这个框架,代码真的挺优美的,今日在做社区的一些功能,心血来潮就参考了p ...

  4. php面试框架的执行流程图,ThinkPHP2.2框架执行流程图,ThinkPHP控制器的执行流程

    ThinkPHP2.2框架执行原理.流程图在线手册 ThinkPHP控制器的执行流程 对用户的第一次URL访问http:///My/index.php/Index/show/所执行的流程进行详细的分析 ...

  5. Struts2和SpringMVC的执行流程。

    先介绍一下SpringMVC的执行流程: 1:客户端发起请求到DispatcherServlet(前端控制器) 2:前端控制器请求HandlerMapping(处理器映射器)查找 Handler 根据 ...

  6. Spring Security 案例实现和执行流程剖析

    在线演示 演示地址:http://139.196.87.48:9002/kitty 用户名:admin 密码:admin Spring Security Spring Security 是 Sprin ...

  7. java之struts2的执行流程讲解(1)

    1.struts2的执行流程 请求--->Tomcat(判读项目是否存在)--->项目的web.xml--->struts2的核心过滤器 --->判读请求的资源(hello.a ...

  8. Spring MVC 拦截器执行流程

    Spring MVC-拦截器 今天就是把有关拦截器的知识做一个总结. 1.拦截器概述 1.1 什么是拦截器? Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(F ...

  9. springcloud gateway 请求执行流程分析

    一.示例 pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http:// ...

最新文章

  1. 从0到1,苏宁API网关的演进之路
  2. BSEG和BSIS、BSAS、BSID、BSAD、BSIK、BSAK六个表的关系
  3. 使用git上传代码到github远程仓库
  4. 一个网络资深者发起的思考
  5. mysql dba命令_MySQL DBA命令
  6. 对项目和产品中坎坎坷坷的一些感悟
  7. java集合框架实验心得_关于Java集合框架的总结
  8. 部署VC2008应用程序
  9. 2寸的照片长宽各是多少_2寸照片的高和宽是多少像素?
  10. 5G NR MIB详解
  11. 9、一篇文章带你看懂5G网络(接入网+承载网+核心网)
  12. 微机原理/汇编语言/8088知识总结
  13. 决策树 基于python实现ID3,C4.5,CART算法
  14. ML:LGBMClassifier、XGBClassifier和CatBoostClassifier的feature_importances_计算方法源代码解读之详细攻略
  15. 手机便签的字体大小怎么调?
  16. 分布式数据库系统面临的问题和挑战
  17. 《uCOS51移植心得》---七年前之《快快乐乐跟我学51单片机操作系统和IP栈》
  18. 技术揭秘 | 互联网广告黑产盛行,如何反作弊?
  19. pygame壁球游戏之节奏型操控型
  20. linkux笔记 37——46

热门文章

  1. Python实践-简单的爬取图片
  2. Matlab: figure的用法
  3. webpack中require的用法
  4. python来画Bad apple! 50行实现视频转字符画
  5. fetch 请求详解
  6. BAT批处理文件 for命令详解
  7. 搭建yum源仓库和配置epel源
  8. 磨牙下酒两相宜—— 越嚼越香的香酥腊牛肉
  9. Delphi 线程的开始、暂停、继续、停止
  10. 电脑访问网络的原理之白话篇