搗蛋phpwind過濾器執行流程

從上一篇咱們就大概就知道過濾器的定義和怎樣去配置,這一節來講說執行流程 php

 

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這個屬性,這個變量到底裏面裝的是什麼呢函數

咱們在控制檯看一下把post

我這裏解釋一下把,這裏的this是windClassProxy的實例,還記得它是怎樣建立的嗎,再貼一下這個代碼this

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

  

關鍵是這裏 spa

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

  建立一個代理類,而後幫定一個事件,把過濾器做爲事件處理其實例化而後等下觸發,不知道爲何要這樣作,想得不是很明白代理

好啦,萬事俱備,只欠東風拉,看看它是這樣運做拉server

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的魔術方法拉,以下blog

 

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,若是沒有,就直接地調用算啦,若是有的話,就加入到鏈條裏token

 

這裏頗有技巧性,看看接口

 * 攔截器的執行入口
	 * 
	 * @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拉 ,有時間畫一個圖出來會比較容易理解拉 

相關文章
相關標籤/搜索