/** * 执行sql并返回结果或结果对象 * * @param string $sql * @param mixed $bind * @access public * @return Onion\Storage\DB\IResult */ public function execute($sql, $bind = null) { if ($bind === null) { $bind = array(); } if (!is_array($bind)) { $bind = array_slice(func_get_args(), 1); } try { $this->connect(); $sth = $sql instanceof \PDOStatement ? $sql : $this->dbh->prepare($sql); if ($sth === false) { return false; } if (!$sth->execute($bind)) { return false; } } catch (\PDOException $ex) { $error = new StorageError($ex->getMessage(), $ex->errorInfo[1], $ex, array('sql' => (string) $sql, 'bind' => $bind, 'native_code' => $ex->errorInfo[0])); fire_event($this, EXECUTE_EXCEPTION_EVENT, $error); throw $error; } fire_event($this, EXECUTE_EVENT, array($sql, $bind)); if (DEBUG) { $log = 'Execute SQL: ' . $sql; if ($bind) { $log .= ' with ' . json_encode($bind); } \Onion\logger('storage')->debug($log); } $sth->setFetchMode(\PDO::FETCH_ASSOC); return $sth; }
function __on_exception($exception, $terminate = true) { try { \Onion\logger()->exception($exception, 8); } catch (\Exception $ex) { } $code = $exception instanceof HttpError ? $exception->getCode() : 500; if (PHP_SAPI == 'cli') { if (!$terminate) { return array($code, array()); } echo $exception; die(1); } $header = $exception instanceof HttpError ? $exception->getHeader() : array(Response::httpStatus(500)); if (DEBUG) { $message = strip_tags($exception->getMessage()); if (strpos($message, "\n") !== false) { $lines = explode("\n", $message); $message = $lines[0]; } $header[] = 'X-Exception-Message: ' . $message; $header[] = 'X-Exception-Code: ' . $exception->getCode(); foreach (explode("\n", $exception->getTraceAsString()) as $index => $line) { $header[] = sprintf('X-Exception-Trace-%d: %s', $index, $line); } } if ($terminate && !headers_sent()) { foreach ($header as $h) { header($h); } } return array($code, $header); }
/** * 分发请求到对应的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); }