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 * @param string $action * @return mixed */ public function dispatch($controller = '', $action = '') { $args = func_get_args(); $controller = $controller != '' ? $controller : $this->request->getControllerName(); $action = $action != '' ? $action : $this->request->getActionName(); $controllerName = $controller; //如果controller以\开头,就不添加默认前缀 Update at 2018-05-29 13:50 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); } array_unshift($funcArgs, $controllerName); $psr4 = Psr4::getInstance(); $this->controllerCls = call_user_func_array(array($psr4, 'loadClass'), $funcArgs); //load beforeRun 不放到具体的Controller里边执行,要不这里的属性controllerCls获取不到值 if(method_exists($this->controllerCls, 'beforeRun') && is_callable(array($this->controllerCls, 'beforeRun'))) { !$this->controllerCls->beforeRun() && exit(); } /**middleWare**/ $this->getMiddleWare($this->controllerCls)->gatherMiddleware(); $next = array_reduce($this->requestMiddleWare,function ($carry, $item){ return function () use ($carry, $item){ return _loadClass($item)->handle(\Qii::getInstance()->request, $carry); }; }, function(){ return true; })(); if ($next === false) { return false; } $method = new \ReflectionMethod($this, 'dispatch'); foreach($method->getParameters() as $property) { $param = $property->getName(); $this->request->setParam($param, $$param); } $this->controllerCls->setRequest($this->request); $this->controllerCls->controllerId = $controller; $this->controllerCls->actionId = $action; $realAction = $action . Register::get(Consts::APP_DEFAULT_ACTION_SUFFIX); //查看是否设置了当前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; //调用初始化方法 if(method_exists($this->actionCls, 'initialization')) { call_user_func_array(array($this->actionCls, 'initialization'), array($this->actionCls)); } //支持多个action对应到同一个文件,调用的方法为 ...Action,如果没有...Action就调用run if (method_exists($this->actionCls, $realAction)) { return $this->actionCls->setResponse(call_user_func_array(array($this->actionCls, $realAction), $funcArgs)); } if (!method_exists($this->actionCls, 'run')) { throw new MethodNotFound(\Qii::i(1101, $this->controllerCls->actions[$action] . '->run'), __LINE__); } return $this->actionCls->setResponse(call_user_func_array(array($this->actionCls, 'run'), array_slice($funcArgs, 1))); } if(method_exists($this->controllerCls, 'initialization')) { call_user_func_array(array($this->controllerCls, 'initialization'), array($this->controllerCls)); } array_shift($funcArgs); if (!method_exists($this->controllerCls, $realAction) && !method_exists($this->controllerCls, '__call')) { throw new MethodNotFound(\Qii::i(1101, $controller . '->' . $realAction), __LINE__); } return $this->controllerCls->setResponse(call_user_func_array(array($this->controllerCls, $realAction), $funcArgs)); } }