捣蛋phpwind过滤器执行流程
从上一篇我们就大概就知道过滤器的定义和怎样去配置,这一节来说说执行流程
- 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拉 ,有时间画一个图出来会比较容易理解拉
捣蛋phpwind过滤器执行流程的更多相关文章
- 捣蛋phpwind之WindFrameWork
一直都有关注phpwind这个开源产品,从9.0开始就好关注拉,因为官方说把之前的代码重写了一遍,融入了windFramework这个框架,代码真的挺优美的,今日在做社区的一些功能,心血来潮就参考了p ...
- 轻量级前端MVVM框架avalon - 执行流程2
接上一章 执行流程1 在这一大堆扫描绑定方法中应该会哪些实现? 首先我们看avalon能帮你做什么? 数据填充,比如表单的一些初始值,切换卡的各个面板的内容({{xxx}},{{xxx|html}}, ...
- ThinkPHP2.2框架执行流程图,ThinkPHP控制器的执行流程
ThinkPHP2.2框架执行原理.流程图在线手册 ThinkPHP控制器的执行流程 对用户的第一次URL访问 http://<serverIp>/My/index.php/Index/s ...
- Servlet、Struts2、SpringMVC执行流程
Servlet 有以下四个阶段: 1.加载和实例化 Servlet容器负责加载和实例化Servlet. 当Servlet容器启动时,或者在容器检测到需要这个Servlet来响应第一个请求时,创建Ser ...
- struts2 之 【struts2简介,struts2开发步骤,struts2详细配置,struts2执行流程】
入门框架学习避免不了的问题: 1. 什么是框架? 简单的说,框架就是模板,模子,模型.就是一个可重用的半成品. 2. 如何学习框架? 学习框架其实就是学习规则,使用框架就是遵循框架的规则,框架是可变的 ...
- Struts框架之 执行流程 struts.xml 配置详细
1.执行流程 服务器启动: 1. 加载项目web.xml 2. 创建Struts核心过滤器对象, 执行filter → init() struts-default.xml, 核心功能的初 ...
- Struts2第二篇【开发步骤、执行流程、struts.xml讲解、defalut-struts讲解】
前言 我们现在学习的是Struts2,其实Struts1和Struts2在技术上是没有很大的关联的.Struts2其实基于Web Work框架的,只不过它的推广没有Struts1好,因此就拿着Stru ...
- Spring Security Oauth2 单点登录案例实现和执行流程剖析
Spring Security Oauth2 OAuth是一个关于授权的开放网络标准,在全世界得到的广泛的应用,目前是2.0的版本.OAuth2在“客户端”与“服务提供商”之间,设置了一个授权层(au ...
- Spring Security 案例实现和执行流程剖析
Spring Security Spring Security 是 Spring 社区的一个顶级项目,也是 Spring Boot 官方推荐使用的安全框架.除了常规的认证(Authentication ...
随机推荐
- 神经网络:卷积神经网络CNN
一.前言 这篇卷积神经网络是前面介绍的多层神经网络的进一步深入,它将深度学习的思想引入到了神经网络当中,通过卷积运算来由浅入深的提取图像的不同层次的特征,而利用神经网络的训练过程让整个网络自动调节卷积 ...
- jenkins的搭建和使用
Jenkins 是一个开源项目,提供了一种易于使用的持续集成系统,使开发者从繁杂的集成中解脱出来,专注于更为重要的业务逻辑实现上.同时 Jenkins 能实施监控集成中存在的错误,提供详细的日志文件和 ...
- 无开发经验,初学python
1.无开发经验,初学python 如果你不会其他语言,python是你的第一门语言: A Byte of Python (简明python教程,这个有中文版简明 Python 教程)是非常好的入门 ...
- Django自定义模型(model)中的字段标签
方法一: 在编辑页面中,每个字段的标签都是从模块的字段名称生成的. 规则很简单: 用空格替换下划线:首字母大写.例如:Book模块中publication_date的标签是Publication da ...
- 《c程序设计语言》读书笔记--反转字符串
#include "stdio.h" #define Num 100 void reverse(char words[]) { int i, j, c, n=0; while(wo ...
- HDU 4752 Polygon(抛物线长度积分)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4752 题意:给出一个抛物线和一个简单多边形.求抛物线在多边形内部的长度. 思路:首先求出多边形所有边和 ...
- 《OD大数据实战》Hive环境搭建
一.搭建hadoop环境 <OD大数据实战>hadoop伪分布式环境搭建 二.Hive环境搭建 1. 准备安装文件 下载地址: http://archive.cloudera.com/cd ...
- Android使用 LruCache 缓存图片
摘要:在你应用程序的UI界面加载一张图片是一件很简单的事情,但是当你需要在界面上加载一大堆图片的时候,情况就变得复杂起来. 使用图片缓存技术 在 你应用程序的UI界面加载一张图片是一件很简单的事情,但 ...
- Android 最火的快速开发框架XUtils
参考:http://www.oschina.net/p/xutils 项目git地址https://github.com/wyouflf/xUtils 目录(?)[-] 最近搜了一些框架供初学者学习比 ...
- 【英语】Bingo口语笔记(13) - Call系列
call off - call it off 取消它 call it a day / call it a night 今天到此结束吧/今晚到此结束吧