/** * Handle errors and exceptions * * If the 'noErrorHandler' front Controller flag has been set, * returns early. * * @param Zend_Controller_Request_Abstract $request * @return void */ protected function _handleError(RThink_Controller_Request $request, RThink_Controller_Response $response) { $frontController = RThink_Controller_Front::getInstance(); if ($frontController->getParam('noErrorHandler')) { return; } if ($this->_isInsideErrorHandlerLoop) { $exceptions = $response->getException(); if (count($exceptions) > $this->_exceptionCountAtFirstEncounter) { // Exception thrown by error handler; tell the front Controller to throw it $frontController->throwExceptions(true); throw array_pop($exceptions); } } // check for an exception AND allow the error handler Controller the option to forward if ($response->isException() && !$this->_isInsideErrorHandlerLoop) { $this->_isInsideErrorHandlerLoop = true; // Get exception information $error = new ArrayObject(array(), ArrayObject::ARRAY_AS_PROPS); $exceptions = $response->getException(); $exception = $exceptions[0]; $error->exception = $exception; $exceptionType = get_class($exception); $error->exception = $exception; switch ($exceptionType) { case 'RThink_Controller_Router_Exception': if (404 == $exception->getCode()) { $error->type = self::EXCEPTION_NO_ROUTE; } else { $error->type = self::EXCEPTION_OTHER; } break; case 'RThink_Controller_Dispatcher_Exception': $error->type = self::EXCEPTION_NO_CONTROLLER; break; case 'RThink_Controller_Action_Exception': if (404 == $exception->getCode()) { $error->type = self::EXCEPTION_NO_ACTION; } else { $error->type = self::EXCEPTION_OTHER; } break; default: $error->type = self::EXCEPTION_OTHER; break; } // get a count of the number of exceptions encountered $this->_exceptionCountAtFirstEncounter = count($exceptions); // Keep a copy of the original Request $error->request = clone $request; // Forward to the error handler $request->setParam('error_handler', $error)->setModuleName($this->getErrorHandlerModule())->setControllerName($this->getErrorHandlerController())->setActionName($this->getErrorHandlerAction())->setDispatched(false); } }
/** * 派遣请求到 Controller/action. * 处理线索 dispatch(RThink_Controller_Front) ->dispatch(RThink_Controller_DispatcherStandard) -> dispatch(RThink_Controller_Action) * 最终还是交由动作控制器自己分发 * * @return void RThink_Controller_Response Response object if returnResponse() is true */ public function dispatch() { $_plugins = array(); if ($this->getParam('plugins')) { // if (!$this->getParam('plugin_path')) { // throw new RThink_Exception("插件注册失败!入口文件没有指定plugin_path!"); // } foreach ($this->getParam('plugins') as $plugin) { // include $this->getParam('plugin_path') . '/' . $plugin . '.php'; include APP_PATH . '/app/plugins/' . $plugin . '.php'; $_plugins[] = new $plugin(); } } if (!$this->getParam('noErrorHandler')) { include 'RThink/Controller/Plugin/ErrorHandler.php'; $_plugins[] = new RThink_Controller_Plugin_ErrorHandler(); } $this->_plugins->registerPlugin($_plugins); /** * 获取请求对象 */ if (null === $this->_request) { $this->getRequest(); } /** * 获取响应对象 */ if (null === $this->_response) { $this->getResponse(); } /** * Initialize Router */ $router = $this->getRouter(); /** * 初始化派遣器 */ $dispatcher = $this->getDispatcher(); $dispatcher->setParams($this->getParams())->setResponse($this->_response); // 开始派遣 try { /** * Notify plugins of Router startup */ $this->_plugins->routeStartup($this->_request, $this->_response); try { $router->route($this->_request); } catch (Exception $e) { if ($this->throwExceptions()) { throw $e; } $this->_response->setException($e); } /** * Notify plugins of Router completion */ $this->_plugins->routeShutdown($this->_request, $this->_response); /** * Notify plugins of dispatch loop startup */ $this->_plugins->dispatchLoopStartup($this->_request, $this->_response); /** * 尝试派遣controller/action.如果 $this->_request表明需要被派遣, * 移动到request的下一个action */ do { $this->_request->setDispatched(true); /** * Notify plugins of dispatch startup */ $this->_plugins->preDispatch($this->_request, $this->_response); /** * 如果 preDispatch() 重置了请求的action则跳过 */ if (false == $this->_request->isDispatched()) { continue; } /** * 派遣请求 */ try { $dispatcher->dispatch($this->_request, $this->_response); } catch (Exception $e) { if ($this->throwExceptions()) { throw $e; } $this->_response->setException($e); } /** * Notify plugins of dispatch completion */ $this->_plugins->postDispatch($this->_request, $this->_response); } while (!$this->_request->isDispatched()); } catch (Exception $e) { if ($this->throwExceptions()) { throw $e; } $this->_response->setException($e); } /** * Notify plugins of dispatch loop completion */ try { $this->_plugins->dispatchLoopShutdown($this->_response); } catch (Exception $e) { if ($this->throwExceptions()) { throw $e; } $this->_response->setException($e); } if ($this->_request->getParam('db_debug')) { RThink_Debug::dbDebug(); } if ($this->returnResponse()) { return $this->_response; } $this->_response->sendResponse(); }
/** * 设定请求action名称 * First attempt to retrieve from Request; then from Request params using * action key; default to default action * Returns formatted action name * * @param RThink_Controller_Request $request * @return string */ public function getActionMethod(RThink_Controller_Request $request) { $action = $request->getActionName(); if (empty($action)) { $action = $this->_default_action; $request->setActionName($action); } return $this->formatActionName($action); }
/** * 从当前PATH_INFO查找匹配路由 并将返回值保存在请求对象中 * * @throws RThink_Controller_Router_Exception * @return RThink_Controller_Request Request object */ public function route(RThink_Controller_Request $request) { $match = $request->getPathInfo(); if ($params = $this->_match($match)) { $this->_setRequestParams($request, $params); } else { class_exists('RThink_Controller_Router_Exception', false) || (require 'RThink/Controller/Router/Exception.php'); throw new RThink_Controller_Router_Exception('No route matched the Request', 404); } return $request; }