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

其实外界一直说这个框架模范了yii,但我觉得这个框架一定是有java功底的人写的,因为真的有很多java的风格和影子,不信?请看下文

启动xdebug ,看下执行流程如何

windClassProxy 是个什么东东,我记得之前学struct2的时候也有类似的这个玩意 ,跟进去看看就知道啦

  1 <?php
  2 /**
  3  * 类代理定义
  4  *
  5  * 通过使用类代理机制,可以实现对类方法或属性的监听过滤机制.<code>
  6  * //相关组件配置,只需设置 proxy为true,就可以通过组件工厂创建一个具有代理功能的类实例对象.
  7  * <component name='windApplication' path='WIND:web.WindWebApplication'
  8  * scope='singleton' proxy='true'>
  9  * <properties>
 10  * <property name='dispatcher' ref='dispatcher' />
 11  * <property name='handlerAdapter' ref='router' />
 12  * </properties>
 13  * </component>
 14  * $object = Wind::getComponents('windApplication');
 15  * $object->registerEventListener('runProcess', new Listener());
 16  * </code>
 17  * @author Qiong Wu <papa0924@gmail.com>
 18  * @copyright ©2003-2103 phpwind.com
 19  * @license http://www.windframework.com
 20  * @version $Id: WindClassProxy.php 3681 2012-06-18 02:45:28Z yishuo $
 21  * @package base
 22  */
 23 class WindClassProxy {
 24     /**
 25      * 默认过滤链类型定义
 26      *
 27      * @var string
 28      */
 29     protected $_class_interceptorChain = 'WIND:filter.WindHandlerInterceptorChain';
 30
 31     /**
 32      * 过滤链对象
 33      *
 34      * @var WindHandlerInterceptorChain
 35      */
 36     private $_interceptorChain = null;
 37     protected $_className = '';
 38     protected $_classPath = '';
 39     protected $_instance = null;
 40     protected $_listener = array();
 41
 42     /**
 43      * @param object $targetObj 需要被代理监听的类对象实例  默认为null
 44      */
 45     public function __construct($targetObject = null) {
 46         $targetObject && $this->registerTargetObject($targetObject);
 47     }
 48
 49     /**
 50      * 注册事件以及事件监听类
 51      *
 52      * 通过调用该方法,将事件以及对事件的监听方法注册进来,当事件方法被调用的时候监听的方法被触发.例:<code>
 53      * <component name='windApplication' path='WIND:web.WindWebApplication'
 54      * scope='singleton' proxy='true'>...</component>
 55      * $object = Wind::getComponents('windApplication');
 56      * $object->registerEventListener('runProcess', new Listener());
 57      * </code>
 58      * @param object $listener 事件监听器
 59      * @param stinrg $event 被监听的事件
 60      * @return void
 61      */
 62     public function registerEventListener($listener, $event) {
 63         $this->_listener[$event][] = $listener;
 64     }
 65
 66     /**
 67      * 注册目标对象,如果已经注册了不重复注册
 68      *
 69      * WindFactory中创建类代理的一段例子:<code>
 70      * $instance = new Object();
 71      * $this->addClassDefinitions($alias, array('path' => $proxy, 'scope' => 'prototype'));
 72      * $proxy = $this->getInstance($alias);
 73      * $proxy->registerTargetObject($instance);
 74      * $instance->_proxy = $proxy;
 75      * </code><note><b>注意:</b>$instance继承自WindModule</note>
 76      * @param object $targetObject
 77      * @return WindClassProxy
 78      */
 79     public function registerTargetObject($targetObject) {
 80         $this->_className = get_class($targetObject);
 81         $this->_instance = $targetObject;
 82         return $this;
 83     }
 84
 85     /**
 86      * 监听类方法
 87      *
 88      * @param string $methodName 方法名
 89      * @param array $args 方法参数
 90      * @return mixed
 91      * @throws WindException
 92      */
 93     public function __call($methodName, $args) {
 94         $listeners = isset($this->_listener[$methodName]) ? $this->_listener[$methodName] : array();
 95         if (empty($listeners)) return call_user_func_array(array($this->_instance, $methodName), $args);
 96         $interceptorChain = $this->_getInterceptorChain($methodName);
 97         $interceptorChain->addInterceptors($listeners);
 98         $interceptorChain->setCallBack(array($this->_getInstance(), $methodName), $args);
 99         return call_user_func_array(array($interceptorChain->getHandler(), 'handle'), (array) $args);
100     }
101
102     /**
103      * 创建并返回过滤链,如果过滤链已经被创建不重复创建
104      *
105      * @param string $event 事件名称 默认值为空
106      * @return WindHandlerInterceptorChain
107      * @throws WindException
108      */
109     private function _getInterceptorChain($event = '') {
110         if (null === $this->_interceptorChain) {
111             $chain = Wind::import($this->_class_interceptorChain);
112             $this->_interceptorChain = WindFactory::createInstance($chain);
113         }
114         $this->_interceptorChain->reset();
115         return $this->_interceptorChain;
116     }
117
118     /**
119      * 返回当前代理对象的真实类对象
120      *
121      * @return object
122      */
123     public function _getInstance() {
124         return $this->_instance;
125     }
126
127     /**
128      * 返回当前代理对象的真实类名称
129      *
130      * @return string
131      */
132     public function _getClassName() {
133         return $this->_className;
134     }
135
136     /**
137      * 返回当前代理对象的真实类的路径信息
138      *
139      * @return string
140      */
141     public function _getClassPath() {
142         return $this->_classPath;
143     }
144
145     /**
146      * 设置类名称
147      *
148      * @param string $className
149      * @return void
150      */
151     public function _setClassName($className) {
152         $this->_className = $className;
153     }
154
155     /**
156      * 设置类路径
157      *
158      * @param string $classPath
159      * @return void
160      */
161     public function _setClassPath($classPath) {
162         $this->_setClassName(Wind::import($classPath));
163         $this->_classPath = $classPath;
164     }
165 }
166 ?>

一个代理类,那么该怎么用呢,先看看下面把

 1     /**
 2      * 解析action过滤链的配置信息
 3      *
 4      * @param WindSimpleController $handler
 5      * @return void
 6      */
 7     protected function resolveActionFilters(&$handler) {
 8         if (!$filters = $this->getConfig('filters')) return;
 9         /* @var $cache AbstractWindCache */
10         $_filters = array();
11         if ($cache = Wind::getComponent('windCache')) {
12             $_filters = $cache->get('filters');
13         }
14         $_token = $this->handlerAdapter->getModule() . '/' . $this->handlerAdapter->getController() . '/' . $this->handlerAdapter->getAction();
15         if (!isset($_filters[$_token])) {
16             foreach ($filters as $_filter) {
17                 if (empty($_filter['class'])) continue;
18                 $_pattern = empty($_filter['pattern']) ? '' : $_filter['pattern'];
19                 unset($_filter['pattern']);
20                 if ($_pattern) {
21                     $_pattern = str_replace(array('*', '/'), array('\w*', '\/'), $_pattern);
22                     if (in_array($_pattern[0], array('~', '!'))) {
23                         $_pattern = substr($_pattern, 1);
24                         if (preg_match('/^' . $_pattern . '$/i', $_token)) continue;
25                     } else {
26                         if (!preg_match('/^' . $_pattern . '$/i', $_token)) continue;
27                     }
28                 }
29                 $_filters[$_token][] = $_filter;
30             }
31             $cache && $cache->set('filters', $_filters);
32         }
33         if (empty($_filters[$_token])) return;
34         /* @var $proxy WindClassProxy */
35         $proxy = WindFactory::createInstance(Wind::import('WIND:filter.proxy.WindClassProxy'));
36         $proxy->registerTargetObject($handler);
37         foreach ($_filters[$_token] as $value) {
38             $proxy->registerEventListener(
39                 $this->factory->createInstance(Wind::import($value['class']),
40                     array($handler->getForward(), $handler->getErrorMessage(), $this->handlerAdapter, $value)),
41                 'doAction');
42         }
43         $handler = $proxy;
44     }

一系列的 filter,跟java好像把是不是 ,看下java是怎样定义fliter的吧

 1 import java.io.*;
 2 import javax.servlet.*;
 3 import javax.servlet.http.*;
 4 import java.util.*;
 5
 6 // 实现 Filter 类
 7 public class LogFilter implements Filter  {
 8    public void  init(FilterConfig config)
 9                          throws ServletException{
10       // 获取初始化参数
11       String testParam = config.getInitParameter("test-param");
12
13       // 输出初始化参数
14       System.out.println("Test Param: " + testParam);
15    }
16    public void  doFilter(ServletRequest request,
17                  ServletResponse response,
18                  FilterChain chain)
19                  throws java.io.IOException, ServletException {
20
21       // 获取客户机的 IP 地址
22       String ipAddress = request.getRemoteAddr();
23
24       // 记录 IP 地址和当前时间戳
25       System.out.println("IP "+ ipAddress + ", Time "
26                                        + new Date().toString());
27
28       // 把请求传回过滤链
29       chain.doFilter(request,response);
30    }
31    public void destroy( ){
32       /* 在 Filter 实例被 Web 容器从服务移除之前调用 */
33    }
34 }

Web.xml 中的 Servlet 过滤器映射(Servlet Filter Mapping)

 1 <filter>
 2    <filter-name>LogFilter</filter-name>
 3    <filter-class>LogFilter</filter-class>
 4    <init-param>
 5       <param-name>test-param</param-name>
 6       <param-value>Initialization Paramter</param-value>
 7    </init-param>
 8 </filter>
 9 <filter-mapping>
10    <filter-name>LogFilter</filter-name>
11    <url-pattern>/*</url-pattern>
12 </filter-mapping>

是不是好像阿,看下这段代码 

 1 $_token = $this->handlerAdapter->getModule() . '/' . $this->handlerAdapter->getController() . '/' . $this->handlerAdapter->getAction();
 2         if (!isset($_filters[$_token])) {
 3             foreach ($filters as $_filter) {
 4                 if (empty($_filter['class'])) continue;
 5                 $_pattern = empty($_filter['pattern']) ? '' : $_filter['pattern'];
 6                 unset($_filter['pattern']);
 7                 if ($_pattern) {
 8                     $_pattern = str_replace(array('*', '/'), array('\w*', '\/'), $_pattern);
 9                     if (in_array($_pattern[0], array('~', '!'))) {
10                         $_pattern = substr($_pattern, 1);
11                         if (preg_match('/^' . $_pattern . '$/i', $_token)) continue;
12                     } else {
13                         if (!preg_match('/^' . $_pattern . '$/i', $_token)) continue;
14                     }
15                 }
16                 $_filters[$_token][] = $_filter;
17             }
18             $cache && $cache->set('filters', $_filters);
19         }

如果url匹配的话,该过滤器就加入执行队列里面

看看phpwind的过滤器是怎样书写的

<?php
Wind::import('WIND:filter.WindActionFilter');/*** * CSRF安全处理filter** @author liusanbian <liusanbian@aliyun.com> * @copyright ©2003-2103 phpwind.com* @license http://www.windframework.com* @version $Id$*/
class PwCsrfTokenFilter extends WindActionFilter {/* (non-PHPdoc)* @see WindHandlerInterceptor::preHandle()*/public function preHandle() {if (true !== $this->getRequest()->isPost() || empty($_POST)) return ;/* @var $windToken IWindSecurityToken */$windToken = Wind::getComponent('windToken');$csrf_token = $this->getInput('csrf_token', 'POST');if (true !== $windToken->validateToken($csrf_token, 'csrf_token')) {$this->errorMessage->sendError('Sorry, CSRF verification failed(token missing or incorrect),refresh to try again.');}}/* (non-PHPdoc)* @see WindHandlerInterceptor::postHandle()*/public function postHandle() {}
}
?>

  

简直就是异曲同工阿 ,再看看它的父类 

<?php
Wind::import('WIND:fitler.WindHandlerInterceptor');
/*** action拦截器父类* 继承实现拦截链preHandle(前置)和postHandle(后置)职责.将实现的拦截链添加到应用配置中,使之生效:* 例如实现MyFilter,则需要在应用配置中添加如下配置:* <code>* 'filters' => array(* 'class' => 'WIND:filter.WindFilterChain',    //设置使用的拦截链实现* 'filter1' => array(* 'class' =>* 'MYAPP:filter.MyFilter',   //设置设置实现的MyFilter类路径,MYAPP必须是一个有效的经过注册的命名空间* 'pattern' => '*',  //此处设置该拦截规则应用的范围,*意味着所有的action都将会应用该拦截规则* )* )* </code>* 关于pattern的设置说明如下:* <ul>* <li>*:则所有的请求都将会应用该拦截器</li>* <li>moduleA*: 则所有配置的moduleA模块下的请求都将会应用该拦截器</li>* <li>moduleA_index*: 则moduleA模块下的indexController下的所有Action请求都将会应用该拦截器</li>* <li>moduleA_index_add*: 则module模块下的indexController下的addAction将会应用该拦截器</li>* </ul>* 用户可以在filter中添加自己的特殊配置:比如:* <code>* 'filters' => array(* 'class' => 'WIND:filter.WindFilterChain',* 'filter1' => array(* 'class' => 'MYAPP:filter.TestFilter',* 'pattern' => '*',* 'isOpen' => '1',   //添加的配置* )* )* </code>* 则在自己的TestFilter中设置一个属性名为isOpen同时设置该属性为protected权限,那么在使用的时候该配置的值将会赋值给该属性.* * @author Qiong Wu <papa0924@gmail.com>* @copyright ©2003-2103 phpwind.com* @license http://www.windframework.com* @version $Id: WindActionFilter.php 3829 2012-11-19 11:13:22Z yishuo $* @package filter*/
abstract class WindActionFilter extends WindHandlerInterceptor {/*** action跳转类* * @var WindForward*/protected $forward = null;/*** 错误处理类* * @var WindErrorMessage*/protected $errorMessage = null;/*** 路由对象* * @var AbstractWindRouter*/protected $router = null;/*** 构造函数* 初始化类属性* * @param WindForward $forward*        设置当前的forward对象* @param WindErrorMessage $errorMessage*        设置错误处理的errorMessage* @param AbstractWindRouter $router*        路由对象* @param array $args*        接受数组传递,数组以关联数组的方式给出,如果存在属性和关联数组中的key相同则将该key对应值设置给该属性.*/public function __construct($forward, $errorMessage, $router, $args = array()) {$this->forward = $forward;$this->errorMessage = $errorMessage;$this->router = $router;foreach ($args as $key => $value)property_exists($this, $key) && $this->$key = $value;}/*** 设置模板数据* 此方法设置的参数,作用域仅仅只是在当前模板中可用,调用的方法为{$varName}* * @param string|array|object $data*        需要设置输出的参数* @param string $key*        参数的名字,默认为空,如果key为空,并且$data是数组或是对象的时候,则$data中的元素将会作为单独的参数保存到输出数据中.*/protected function setOutput($data, $key = '') {$this->forward->setVars($data, $key);}/*** 从指定源中根据输入的参数名获得输入数据* * @param string $name*        需要获取的值的key* @param string $type*        获取数据源,可以是(GET POST COOKIE)中的一个,每种都将从各自的源中去获取对应的数值:*        <ul>*        <li>GET: 将从$_GET中去获取数据</li>*        <li>POST: 将从$_POST中去获取数据</li>*        <li>COOKIE: 将从$_COOKIE中去获取数据</li>*        <li>其他值:*        将依次从request对象的attribute,$_GET,$_POST,$_COOKIE,$_REQUEST,$_ENV,$_SERVER中去尝试获取该值.</li>*        </ul>*        该参数默认为空* @return array string <ul>*         <li>第一个元素: 获得的用户输入的值</li>*         <li>第二个元素:执行$callback之后返回的值</li>*         </ul>*/protected function getInput($name, $type = '') {$value = '';switch (strtolower($type)) {case 'get':$value = $this->getRequest()->getGet($name);break;case 'post':$value = $this->getRequest()->getPost($name);break;case 'cookie':$value = $this->getRequest()->getCookie($name);break;default:$value = $this->getRequest()->getRequest($name);}return $value;}
}
?>

  

下面这个类才是关键 

<?php
/*** 拦截器基类* * 该类是拦截器机制的核心实现,提供接口:* <ul>* <li>{@link preHandle()}: 抽象接口,前置操作,需要子类实现</li>* <li>{@link postHandle()}: 抽象接口,后置操作,需要子类实现</li>* <li>{@link handle()}: 入口接口,调用拦截器的实现.</li>* </ul>* 该拦截器需要配合拦截链WindHandlerInterceptorChain实现真正的拦截链.** the last known user to change this file in the repository  <$LastChangedBy: yishuo $>* @author Qiong Wu <papa0924@gmail.com>* @copyright ©2003-2103 phpwind.com* @license http://www.windframework.com* @version $Id: WindHandlerInterceptor.php 3113 2011-11-11 07:28:09Z yishuo $* @package filter*/
abstract class WindHandlerInterceptor extends WindModule {/*** 保存执行的结果 ** @var mixed*/protected $result = null;/*** 保存拦截链* * 用以传递控制到下一个拦截器** @var WindHandlerInterceptorChain*/protected $interceptorChain = null;/*** 拦截器的前置操作* * @param mixed $var=.. 参数列表将会从handle接口中传递继承* @return null|mixed 如果返回为null则将会继续执行下一个拦截器,如果返回不为null则会中断拦截链的执行*/abstract public function preHandle();/*** 拦截器的后置操作* * @param mixed $var=.. 参数列表将会从handle接口中传递继承*/abstract public function postHandle();/*** 拦截器的执行入口* * @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);} else {$this->result = call_user_func_array(array($this->interceptorChain, 'handle'), $args);}call_user_func_array(array($this, 'postHandle'), $args);return $this->result;}/*** 设置拦截链对象* * @param WindHandlerInterceptorChain $interceptorChain*/public function setHandlerInterceptorChain($interceptorChain) {$this->interceptorChain = $interceptorChain;}
}
?>

  

preHandle 和  postHandle 这两个方法是抽象的,需要子类实现的,handle这个东西可以在子类调用阿 

而且 setHandlerInterceptorChain  这个可以换不同的拦截器链,比较灵活把

今日就分享到这里吧,下节再继续

---恢复内容结束---

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

捣蛋phpwind之WindFrameWork相关推荐

  1. 捣蛋phpwind控制器注入

    在PwBaseController 里面,会有这个方法的存在 /*** action Hook 注册** @param string $registerKey 扩展点别名* @param PwBase ...

  2. 捣蛋phpwind过滤器执行流程

    从上一篇我们就大概就知道过滤器的定义和怎样去配置,这一节来说说执行流程 public function run($handlerAdapter = null) {$handlerAdapter !== ...

  3. onethink和phpwind共用

    将onethink和phpwind数据库安装在一起,使用通用的表前缀. 将onethink的member表指向phpwind有user表 以下为onethink安装在根目录下,phpwind安装在bb ...

  4. php7伪静态 源码,PHPWind 8.5和8.7版的伪静态.htaccess规则

    日前PHPWind发布了8.7的新版本,站长们升级后有些伪静态规则不能使用.本文介绍修改Apache的.htaccess来实现伪静态的效果,效果如下:http://www.phpwind.net/fx ...

  5. linux下的PHP+Mysql+PHPWind实现

    linux下的PHP+Mysql+PHPWind实现 1安装httpd.mysql mysql-server php php-mysql php-mbstring yum -y install mys ...

  6. ubuntu平台下搭建PHPWind网站运行环境

    ubuntu平台下搭建PHPWind网站运行环境 前提: 要打开root权限 sudo password [这里填写root密码] 在Linux平台安装PhpWind的是比较麻烦的事,相对来说在Ubu ...

  7. php怎么添加框架,PHPWind 给默认的风格添加大框架

    虽然大框架会影响一些速度,但是对于新做风格的朋友来说,一个大框架也是一个最简单直接的美化方式,学会这个简单的大框架,也就可以运用到其他的地方. 准备工作:我们要按照官方已有的风格教程定义一套新的风格, ...

  8. mysql phpwind_【phpwind教程:Linux Apache php MySQL GD PHPWind 集成环境配置】-phpwind教程-【零度中国】...

    继PHPWind Wamp 1.0 后,PHPWind 开发团队总结多年Linux下web环境安装的经验,推出全新软件包PHPWind LAMP 1.0. 为了获得更好.更灵活的配置效果,PHPWin ...

  9. phpwind管理权限泄露漏洞

    漏洞说明:phpwind是国内使用非常广泛的一款程序,由于在程序设计上存在错误,导致任何人可以取得前台管理员及斑主权限,做删除帖子等任意操作 漏洞分析:由于phpwind论坛在设计上对数据库存储机制不 ...

最新文章

  1. linux下测试个人主页,一键建站集成软件包,Linux上快速搭建测试个人网站
  2. 拼图项目的诅咒:为什么Java 9一遍又一遍地延迟?
  3. 快速入门人工智能的方法,持续更新ing
  4. C++新特性探究(三):=default、=delete
  5. java long 1 000_Java-基本数据类型
  6. Linux 内存管理:DAX(Direct Access)机制的作用及实现原理
  7. 22考研清华电子系957,390+高分上岸初复试经验分享
  8. linux qt编译器设置,Qt使用教程:添加编译器(一)
  9. Pycocotools 报error: Microsoft Visual C++ 14.0 or greater is required. Get it with “Microsoft C++ Bui
  10. supersu二进制更新安装失败_Supersu提示更新二进制文件解决方案
  11. Vscode删除空白行
  12. Linux CreateRepo创建Repomd (xml-rpm-metadata)存储库
  13. java程序员必读书籍
  14. 数字经济新基建巨头:VMware公司研究
  15. 苹果手机隐私分析数据是什么_苹果和谷歌可能是我们在隐私操作系统上的最佳选择...
  16. FPGA之简易频率计的设计
  17. 程序人生--2003年(20)
  18. matlab如何打开flt文件,FIT文件格式解析及MATLAB读取程序
  19. PAT乙级 1012 数字分类 (20 分)
  20. 教Kindle新手 手动升级Kindle固件至5.8.5.0.1 全过程

热门文章

  1. win10 服务器文件夹权限,Win10无权限也能访问特殊文件夹的解决方法
  2. 平板电脑 android 2,搭载Android2.2 万利达T2平板电脑评测
  3. 企业参加社会保险须知(缴费比例表)
  4. 第二银河找不到更新服务器,第二银河空间排斥操作是什么 为什么会突然回到...
  5. mc服务器怎么做交易系统,《我的世界》村民交易系统详解
  6. 《我不是药神》与AI研制新药
  7. 链脉名片是如何解决,中国企业智能数据库管理问题
  8. 若依框架模块名称修改
  9. 批处理基础知识-IF
  10. 夏至未至计算机版音乐,夏至未至有哪些插曲背景音乐 夏至未至所有bgm歌曲汇总...