|
@@ -3,6 +3,8 @@ namespace Qii\Base;
|
|
|
|
|
|
use \Qii\Config\Register;
|
|
|
use \Qii\Config\Consts;
|
|
|
+use Qii\Exceptions\MethodNotFound;
|
|
|
+use Qii\Request\Http;
|
|
|
|
|
|
class Dispatcher
|
|
|
{
|
|
@@ -12,20 +14,62 @@ class Dispatcher
|
|
|
|
|
|
public $actionCls = null;
|
|
|
|
|
|
+ private $requestMiddleWare = array();
|
|
|
+
|
|
|
public function __construct()
|
|
|
{
|
|
|
|
|
|
}
|
|
|
/**
|
|
|
* 设置请求
|
|
|
- * @param \Qii\Request\Http $request 当前请求
|
|
|
+ * @param Http $request 当前请求
|
|
|
*/
|
|
|
- public function setRequest(\Qii\Request\Http $request)
|
|
|
+ public function setRequest(Http $request)
|
|
|
{
|
|
|
$this->request = $request;
|
|
|
return $this;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 设置中间件
|
|
|
+ *
|
|
|
+ * @param array $middleware 中间件
|
|
|
+ * @return $this
|
|
|
+ */
|
|
|
+ public function setMiddleware($middleware) {
|
|
|
+ if (!is_array($middleware)) {
|
|
|
+ return $this;
|
|
|
+ }
|
|
|
+ $this->requestMiddleWare = array_merge($this->requestMiddleWare, $middleware);
|
|
|
+ return $this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取 controller 设置的middleware
|
|
|
+ * @param $controller
|
|
|
+ * @return $this
|
|
|
+ */
|
|
|
+ public function getMiddleWare($controller)
|
|
|
+ {
|
|
|
+ if (method_exists($controller, 'getMiddleware')) {
|
|
|
+ $this->requestMiddleWare = array_merge($this->requestMiddleWare, $controller->getMiddleware());
|
|
|
+ }
|
|
|
+ return $this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 整理 middleware
|
|
|
+ * @return $this
|
|
|
+ */
|
|
|
+ public function gatherMiddleware()
|
|
|
+ {
|
|
|
+ if(count($this->requestMiddleWare) == 0) {
|
|
|
+ return $this;
|
|
|
+ }
|
|
|
+ $this->requestMiddleWare = array_unique($this->requestMiddleWare);
|
|
|
+ return $this;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 转发
|
|
|
* @param string $controller
|
|
@@ -43,6 +87,7 @@ class Dispatcher
|
|
|
if(substr($controller,0, 1) != '\\') {
|
|
|
$controllerName = Register::get(Consts::APP_DEFAULT_CONTROLLER_PREFIX) . '_' . $controller;
|
|
|
}
|
|
|
+
|
|
|
$funcArgs = array();
|
|
|
if (count($args) > 2) {
|
|
|
$funcArgs = array_slice($args, 2);
|
|
@@ -51,52 +96,60 @@ class Dispatcher
|
|
|
$psr4 = \Qii\Autoloader\Psr4::getInstance();
|
|
|
$controllerCls = call_user_func_array(array($psr4, 'loadClass'), $funcArgs);
|
|
|
|
|
|
- $method = new \ReflectionMethod($this, 'dispatch');
|
|
|
- foreach($method->getParameters() as $property)
|
|
|
- {
|
|
|
- $param = $property->getName();
|
|
|
- $this->request->setParam($param, $$param);
|
|
|
- }
|
|
|
- $this->controllerCls = $controllerCls;
|
|
|
- $this->controllerCls->setRequest($this->request);
|
|
|
- $this->controllerCls->controller = $controllerCls;
|
|
|
- $this->controllerCls->controllerId = $controller;
|
|
|
- $this->controllerCls->actionId = $action;
|
|
|
- $response = null;
|
|
|
- //查看是否设置了当前action的对应关系,如果设置了就走对应关系里边的,否则走当前类中的
|
|
|
- if ($this->controllerCls->actions && isset($this->controllerCls->actions[$action]) && $this->controllerCls->actions[$action]) {
|
|
|
- $actionArgs = array();
|
|
|
- $actionArgs[] = $this->controllerCls->actions[$action];
|
|
|
- $actionCls = call_user_func_array(array($psr4, 'loadClass'), $actionArgs);
|
|
|
- $this->actionCls = $actionCls;
|
|
|
- $this->actionCls->setRequest($this->request);
|
|
|
- $this->actionCls->controller = $this->controllerCls;
|
|
|
- $this->actionCls->actionId = $action;
|
|
|
- $this->actionCls->controllerId = $this->controllerCls->controllerId;
|
|
|
- //支持多个action对应到同一个文件,如果对应的文件中存在指定的方法就直接调用
|
|
|
- if (method_exists($this->actionCls, $action . Register::get(Consts::APP_DEFAULT_ACTION_SUFFIX))) {
|
|
|
- $this->actionCls->response = $response = call_user_func_array(array($this->actionCls, $action. Register::get(Consts::APP_DEFAULT_ACTION_SUFFIX)), $funcArgs);
|
|
|
- }
|
|
|
- if(method_exists($this->actionCls, 'initialization'))
|
|
|
+ /**middleWare**/
|
|
|
+ $this->getMiddleWare($controllerCls)->gatherMiddleware();
|
|
|
+ $pipeline = array_reduce($this->requestMiddleWare,function ($carry, $item){
|
|
|
+ return function () use ($carry, $item){
|
|
|
+ return _loadClass($item)->handle(\Qii::getInstance()->request, $carry);
|
|
|
+ };
|
|
|
+ }, function($funcArgs, $controllerCls, $psr4, $controller, $action){$method = new \ReflectionMethod($this, 'dispatch');
|
|
|
+ foreach($method->getParameters() as $property)
|
|
|
{
|
|
|
- call_user_func_array(array($this->actionCls, 'initialization'), array($this->actionCls));
|
|
|
+ $param = $property->getName();
|
|
|
+ $this->request->setParam($param, $$param);
|
|
|
}
|
|
|
- if (!method_exists($this->actionCls, 'run')) {
|
|
|
- throw new \Qii\Exceptions\MethodNotFound(\Qii::i(1101, $this->controllerCls->actions[$action] . '->run'), __LINE__);
|
|
|
+ $this->controllerCls = $controllerCls;
|
|
|
+ $this->controllerCls->setRequest($this->request);
|
|
|
+ $this->controllerCls->controller = $controllerCls;
|
|
|
+ $this->controllerCls->controllerId = $controller;
|
|
|
+ $this->controllerCls->actionId = $action;
|
|
|
+
|
|
|
+ //查看是否设置了当前action的对应关系,如果设置了就走对应关系里边的,否则走当前类中的
|
|
|
+ if ($this->controllerCls->actions
|
|
|
+ && isset($this->controllerCls->actions[$action])
|
|
|
+ && $this->controllerCls->actions[$action]) {
|
|
|
+ $actionArgs = array();
|
|
|
+ $actionArgs[] = $this->controllerCls->actions[$action];
|
|
|
+ $actionCls = call_user_func_array(array($psr4, 'loadClass'), $actionArgs);
|
|
|
+ $this->actionCls = $actionCls;
|
|
|
+ $this->actionCls->setRequest($this->request);
|
|
|
+ $this->actionCls->controller = $this->controllerCls;
|
|
|
+ $this->actionCls->actionId = $action;
|
|
|
+ $this->actionCls->controllerId = $this->controllerCls->controllerId;
|
|
|
+ //支持多个action对应到同一个文件,如果对应的文件中存在指定的方法就直接调用
|
|
|
+ if (method_exists($this->actionCls, $action . Register::get(Consts::APP_DEFAULT_ACTION_SUFFIX))) {
|
|
|
+ $this->actionCls->response = $response = call_user_func_array(array($this->actionCls, $action. Register::get(Consts::APP_DEFAULT_ACTION_SUFFIX)), $funcArgs);
|
|
|
+ }
|
|
|
+ if(method_exists($this->actionCls, 'initialization')) {
|
|
|
+ call_user_func_array(array($this->actionCls, 'initialization'), array($this->actionCls));
|
|
|
+ }
|
|
|
+ if (!method_exists($this->actionCls, 'run')) {
|
|
|
+ throw new MethodNotFound(\Qii::i(1101, $this->controllerCls->actions[$action] . '->run'), __LINE__);
|
|
|
+ }
|
|
|
+ return call_user_func_array(array($this->actionCls, 'run'), array_slice($funcArgs, 1));
|
|
|
}
|
|
|
- $response = call_user_func_array(array($this->actionCls, 'run'), array_slice($funcArgs, 1));
|
|
|
- } else {
|
|
|
- if(method_exists($this->controllerCls, 'initialization'))
|
|
|
- {
|
|
|
+
|
|
|
+ if(method_exists($this->controllerCls, 'initialization')) {
|
|
|
call_user_func_array(array($this->controllerCls, 'initialization'), array($this->controllerCls));
|
|
|
}
|
|
|
array_shift($funcArgs);
|
|
|
$actionName = $action . Register::get(Consts::APP_DEFAULT_ACTION_SUFFIX);
|
|
|
if (!method_exists($this->controllerCls, $actionName) && !method_exists($this->controllerCls, '__call')) {
|
|
|
- throw new \Qii\Exceptions\MethodNotFound(\Qii::i(1101, $controller . '->' . $actionName), __LINE__);
|
|
|
+ throw new MethodNotFound(\Qii::i(1101, $controller . '->' . $actionName), __LINE__);
|
|
|
}
|
|
|
$this->controllerCls->response = $response = call_user_func_array(array($this->controllerCls, $actionName), $funcArgs);
|
|
|
- }
|
|
|
- return $response;
|
|
|
+ return $response;
|
|
|
+ });
|
|
|
+ return call_user_func($pipeline, $funcArgs, $controllerCls, $psr4, $controller, $action);
|
|
|
}
|
|
|
}
|