我正在尝试在我的项目中实现异常处理,并且遇到了一些麻烦。
代码流:一个请求到达 index.php 页面,该页面引入了一个引导文件。该引导文件定义常量,引入其他文件,注册函数等,以“启动”系统。引导程序做了两个主要的事情:定义/注册我的自动加载函数,然后通过需要一个包含异常处理代码的 error.php 文件来对异常处理做同样的事情。引导文件加载后,路由发生,系统离开。
我的问题来自以下。我在系统中有一个类文件文件夹。只是具有各种用途的静态方法的类 - 数据库、会话、用户等。所有这些类都会引发我注册的异常处理程序捕获的各种异常(标准和 SPL)。但是,异常处理程序没有捕获 Session 类的抛出异常。
会话类是一个具有静态方法的类(常规,非抽象/静态),这些静态方法可以“扩展”/“替换”默认的 PHP 会话函数,以便将会话数据存储在数据库中。在 start() 函数中,我通过 session_set_save_handler 函数向 php 会话“句柄”注册了适当的函数。我还按照 php.net 的建议调用 register_shutdown_function 以确保在应用程序必须突然停止时保存会话数据。
这是我的会话类的一些代码,由于我的 SQL 错误而引发了 PDOExceptoin - DB 只是 PDO 的包装器:
public static function write($id, $data) {
try {
$expires = time() + self::$lifetime;
$sql = "INSERT INTO sessions (session_id, session_data, expires) VALUES (?,?,?) ON DUPLICATE KEY UPDATE SET session_data = ? WHERE session_id = ? ";
if (DB::query($sql, array($id, $data, $expires, $data, $id))->rowCount() > 0) {
return true;
} else {
return false;
}
} catch (Exception $e) {
return $e->getMessage();
}
}
- 如果我删除了 catch/try,我会收到一个致命的“未捕获 PDOException”错误。
- 如果我尝试使用 PDOExceptoin 消息在 catch 块中重新抛出一个新异常,那么 PHP 在页面底部会吐出一条致命错误消息。它还吐出异常消息和完整的异常跟踪。
- 如果我在 catch 块中回显异常消息,它将很好地打印出来并且没有致命的未捕获异常错误。
这是我的异常处理error.php文件
// Error handler function
function log_error($num, $str, $file, $line, $context = null) {
log_exception(new ErrorException($str, 0, $num, $file, $line));
}
// Exception handler function
function log_exception($e) {
if (DEBUG) {
$type = get_class($e);
$trace = $e->getTrace();
$error = /* Code that creates an HTML table for pretty exception printing */;
echo "";
echo $error;
echo "";
} else {
$message = "Type: " . get_class($e) . "; Message: {$e->getMessage()}; File: {$e->getFile()}; Line: {$e ->getLine()};";
file_put_contents(SYSPATH . "/private/log/exceptions.log", $message . PHP_EOL, FILE_APPEND);
header("Location: 500.html");
}
}
// Checks for a fatal error, work around for set_error_handler not working on fatal errors.
function check_for_fatal() {
$error = error_get_last();
if ($error["type"] == E_ERROR)
log_error($error["type"], $error["message"], $error["file"],$error["line"]);
}
set_error_handler("log_error");
set_exception_handler("log_exception");
register_shutdown_function("check_for_fatal");
我确实意识到我的 SQL 语句是错误的,这导致了 PDOException,但我现在将其留下来找出我的异常错误。
我相信这与我在两个不同的地方两次调用 register_shutdown_function 的事实有关,尽管 PHP 说它是合法的,并且函数将按照它们注册的顺序被调用,所以也许我的顺序是向后的,或者可能是 PHP并没有真正按顺序调用它们,只是注册的最后一个函数?
编辑:我尝试了以下方法来确认一些事情。
- 正在加载 error.php 文件。如果我在文件中定义一个常量并稍后在 index.php 文件中打印出来,它就会打印出来。
- 在我的引导程序包含在索引页面中之后,我可以在 index.php 中引发异常并且异常按预期执行
- 我可以从给出异常的静态 DB 函数中打印出错误消息,因此 try/catch 处理在静态函数内部工作