搗蛋phpwind之WindFrameWork

 

        一直都有關注phpwind這個開源產品,從9.0開始就好關注拉,由於官方說把以前的代碼重寫了一遍,融入了windFramework這個框架,代碼真的挺優美的,今日在作社區的一些功能,心血來潮就參考了phpwind的代碼,確實學到了很多 php

其實外界一直說這個框架模範了yii,但我以爲這個框架必定是有java功底的人寫的,由於真的有不少java的風格和影子,不信?請看下文 java

       

啓動xdebug ,看下執行流程如何web

 

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的吧 cookie

 

 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>

是否是好像阿,看下這段代碼 app

 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的過濾器是怎樣書寫的yii

<?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  這個能夠換不一樣的攔截器鏈,比較靈活把

今日就分享到這裏吧,下節再繼續




 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

---恢復內容結束---

相關文章
相關標籤/搜索