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

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

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

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

 <?php
/**
* 类代理定义
*
* 通过使用类代理机制,可以实现对类方法或属性的监听过滤机制.<code>
* //相关组件配置,只需设置 proxy为true,就可以通过组件工厂创建一个具有代理功能的类实例对象.
* <component name='windApplication' path='WIND:web.WindWebApplication'
* scope='singleton' proxy='true'>
* <properties>
* <property name='dispatcher' ref='dispatcher' />
* <property name='handlerAdapter' ref='router' />
* </properties>
* </component>
* $object = Wind::getComponents('windApplication');
* $object->registerEventListener('runProcess', new Listener());
* </code>
* @author Qiong Wu <papa0924@gmail.com>
* @copyright ©2003-2103 phpwind.com
* @license http://www.windframework.com
* @version $Id: WindClassProxy.php 3681 2012-06-18 02:45:28Z yishuo $
* @package base
*/
class WindClassProxy {
/**
* 默认过滤链类型定义
*
* @var string
*/
protected $_class_interceptorChain = 'WIND:filter.WindHandlerInterceptorChain'; /**
* 过滤链对象
*
* @var WindHandlerInterceptorChain
*/
private $_interceptorChain = null;
protected $_className = '';
protected $_classPath = '';
protected $_instance = null;
protected $_listener = array(); /**
* @param object $targetObj 需要被代理监听的类对象实例 默认为null
*/
public function __construct($targetObject = null) {
$targetObject && $this->registerTargetObject($targetObject);
} /**
* 注册事件以及事件监听类
*
* 通过调用该方法,将事件以及对事件的监听方法注册进来,当事件方法被调用的时候监听的方法被触发.例:<code>
* <component name='windApplication' path='WIND:web.WindWebApplication'
* scope='singleton' proxy='true'>...</component>
* $object = Wind::getComponents('windApplication');
* $object->registerEventListener('runProcess', new Listener());
* </code>
* @param object $listener 事件监听器
* @param stinrg $event 被监听的事件
* @return void
*/
public function registerEventListener($listener, $event) {
$this->_listener[$event][] = $listener;
} /**
* 注册目标对象,如果已经注册了不重复注册
*
* WindFactory中创建类代理的一段例子:<code>
* $instance = new Object();
* $this->addClassDefinitions($alias, array('path' => $proxy, 'scope' => 'prototype'));
* $proxy = $this->getInstance($alias);
* $proxy->registerTargetObject($instance);
* $instance->_proxy = $proxy;
* </code><note><b>注意:</b>$instance继承自WindModule</note>
* @param object $targetObject
* @return WindClassProxy
*/
public function registerTargetObject($targetObject) {
$this->_className = get_class($targetObject);
$this->_instance = $targetObject;
return $this;
} /**
* 监听类方法
*
* @param string $methodName 方法名
* @param array $args 方法参数
* @return mixed
* @throws WindException
*/
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);
} /**
* 创建并返回过滤链,如果过滤链已经被创建不重复创建
*
* @param string $event 事件名称 默认值为空
* @return WindHandlerInterceptorChain
* @throws WindException
*/
private function _getInterceptorChain($event = '') {
if (null === $this->_interceptorChain) {
$chain = Wind::import($this->_class_interceptorChain);
$this->_interceptorChain = WindFactory::createInstance($chain);
}
$this->_interceptorChain->reset();
return $this->_interceptorChain;
} /**
* 返回当前代理对象的真实类对象
*
* @return object
*/
public function _getInstance() {
return $this->_instance;
} /**
* 返回当前代理对象的真实类名称
*
* @return string
*/
public function _getClassName() {
return $this->_className;
} /**
* 返回当前代理对象的真实类的路径信息
*
* @return string
*/
public function _getClassPath() {
return $this->_classPath;
} /**
* 设置类名称
*
* @param string $className
* @return void
*/
public function _setClassName($className) {
$this->_className = $className;
} /**
* 设置类路径
*
* @param string $classPath
* @return void
*/
public function _setClassPath($classPath) {
$this->_setClassName(Wind::import($classPath));
$this->_classPath = $classPath;
}
}
?>

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

     /**
* 解析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;
}

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

 import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*; // 实现 Filter 类
public class LogFilter implements Filter {
public void init(FilterConfig config)
throws ServletException{
// 获取初始化参数
String testParam = config.getInitParameter("test-param"); // 输出初始化参数
System.out.println("Test Param: " + testParam);
}
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws java.io.IOException, ServletException { // 获取客户机的 IP 地址
String ipAddress = request.getRemoteAddr(); // 记录 IP 地址和当前时间戳
System.out.println("IP "+ ipAddress + ", Time "
+ new Date().toString()); // 把请求传回过滤链
chain.doFilter(request,response);
}
public void destroy( ){
/* 在 Filter 实例被 Web 容器从服务移除之前调用 */
}
}

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

 <filter>
<filter-name>LogFilter</filter-name>
<filter-class>LogFilter</filter-class>
<init-param>
<param-name>test-param</param-name>
<param-value>Initialization Paramter</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>LogFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

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

 $_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);
}

如果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  这个可以换不同的拦截器链,比较灵活把

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

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

捣蛋phpwind之WindFrameWork的更多相关文章

  1. 捣蛋phpwind控制器注入

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

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

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

  3. onethink和phpwind共享

    将onethink和phpwind数据库安装在一起.使用公用表前缀. 将onethink的member表点phpwind有user表 这是onethink在根文件夹的安装,phpwind安装在bbs的 ...

  4. phpwind ecshop 用户整合

    phpwind ecshop 用户整合,其实很简单.但在网上搜到的尽是乱七八遭的方法,搞得很复杂. 原来公司做的phpwind 与 ecshop 结合的项目,别的同事已经把用户整合好了,当时我还不知道 ...

  5. phpwind < v6 版本命令执行漏洞

    phpwind/sort.php 会定期每天处理一次帖子的浏览量.回复量.精华版排序 代码直接使用savearray将数据库查询出来的内容写入php文件,savearray出来的参数,都使用" ...

  6. PHPwind高级伪静态规则及方法

    phpwind iis下伪静态规则[ISAPI_Rewrite]RewriteRule ^(.*)/(.*)-htm-(.*)-(.*)\.html$ $1/$2\.php\?$3=$4Rewrite ...

  7. Linux phpwind论坛的安装

    1:新建文件夹phpwind

  8. phpwind之关闭账号通

    phpwind的账号通功能早就失效了,但是首页的链接一直存在,造成了很不好的影响 但是后台打开账号通功能又打不开,所以想到了在前端的模板中通过屏蔽这部分代码的方法隐藏掉这个功能在首页的显示 1.打开/ ...

  9. PHP框架中最喜欢的WindFramework

    题外话, 像我这样从小到大作文打0分居多的人,写文章,实在是没有耐心的,抱歉. 尽管自己也山寨过许多PHP框架,但被山寨的对象中,最喜欢的是WindFramework. Yii其实更好,但太大而全. ...

随机推荐

  1. 转: Ubuntu 安装字体方法

    命令安装:   以微软雅黑字体为例(其他的宋体.黑体等点阵字体都一样的),我们的雅黑字体文件是:Yahei.ttf(放在自己的主目录下)(在widows目录的Fonts目录下找需要的字体)由于我是双系 ...

  2. RSpec自定义matcher

    链接 https://relishapp.com/rspec/rspec-expectations/v/3-4/docs/custom-matchers/define-a-custom-matcher ...

  3. 20145305 《Java程序设计》第7周学习总结

    教材学习内容总结 1.只有Lambda表达式,参数的类型必须写出来,如果有目标类型,在编译程序可推断出类型的情况下,可以不写出 2.Lambda表达式本身是中性的,不代表任何类型的实例,可用来表示不同 ...

  4. SQL锁表解决并发性

    在数据库开发过程中,不得不考虑并发性的问题,因为很有可能当别人正在更新表中记录时,你又从该表中读数据,那你读出来的数据有可能就不是你希望得到的数据.可以说有些数据同时只能有一个事物去更新,否则最终显示 ...

  5. poj 1007 (nyoj 160) DNA Sorting

    点击打开链接 DNA Sorting Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 75164   Accepted: 30 ...

  6. (medium)LeetCode 224.Basic Calculator

    Implement a basic calculator to evaluate a simple expression string. The expression string may conta ...

  7. (easy)LeetCode 219.Contains Duplicate II

    Given an array of integers and an integer k, find out whether there there are two distinct indices i ...

  8. relatedTarget、fromElement、toElement之间的关系

    在发生mouseover和mouseout事件时会把鼠标指针从一个元素的边界之内移到另一个元素边界之内.对 mouseover事件而言,事件的target是获得光标的元素,而relatedTarget ...

  9. 为textarea增加maxlength属性(转)

    如果只是單純地想限制 textarea 中的字數,不想寫太多的話,可用:   <textarea onkeyup="this.value = this.value.slice(0, 8 ...

  10. java——操作文件

    Java文件操作,共实现了文件复制(单个文件和多层目录文件),文件移动(单个文件和多层目录文件),文件删除(单个文件和多层目录文件),文件压缩 (单个文件),文件解压(单个文件),文件分割(将一个大文 ...