/** * 执行application * * @access public * @return mixed */ public function run() { $req = req(); if (!in_array($req->method(), static::$support_method)) { throw HttpError::not_implemented(); } $url = parse_url($req->requestUri()); return $this->dispatch($url['path']); }
/** * 分发请求到对应的controller * 执行并返回结果 * * @param string $url * @param array $params * @access public * @return mixed */ public function dispatch($url, array $params = array()) { if (DEBUG) { $logger = \Onion\logger('mvc'); } $url = strtolower(rtrim($url, '/')); if (DEBUG) { $logger->info('Request url:' . req()->requestUri()); } list($class, $args) = $this->match($url); if (DEBUG) { $logger->debug('Dispatch url to controller: ' . $class); } if (!$class || !class_exists($class)) { throw HttpError::page_not_found(array('controller' => $class)); } if ($params) { $args = array_merge($args, $params); } fire_event($this, BEFORE_DISPATCH_EVENT, array($url, $class, $args)); $controller = new $class(); if (method_exists($controller, '__before_run')) { // 如果__before_run返回了内容,就直接完成动作 // 可以在这里进行某些阻断操作 // 正常的内容不应该通过这里输出 if ($resp = call_user_func_array(array($controller, '__before_run'), $args)) { return $resp instanceof Response ? $resp : resp()->setBody($resp); } } $request = req(); $method = $request->method(); // head方法除了不输出数据之外,和get方法没有区别 if ($method == 'HEAD') { $method = 'GET'; } if (DEBUG) { $log = 'Call controller [' . $class . '] method [' . $method . ']'; if ($args) { $log .= ' with ' . json_encode($args); } $logger->info($log); } // 执行controller动作并返回结果 // 不检查method是否存在,用is_callable() // 保留__call()重载方法的方式 if (!is_callable(array($controller, $method))) { throw HttpError::method_not_allowed(array('url' => $url, 'class' => $class)); } $resp = call_user_func_array(array($controller, $method), $args); // 这里有机会对输出结果进行进一步处理 if (method_exists($controller, '__after_run')) { $controller->__after_run($resp); } fire_event($this, AFTER_DISPATCH_EVENT, array($url, $class, $args, $resp)); return $resp instanceof Response ? $resp : resp()->setBody($resp); }