从静态方法中捕获抛出的异常

时间:2013-07-08 22:09:32

标签: php exception-handling pdo

我正在尝试在我的项目中实现异常处理,并且有点头疼。

代码流:请求命中index.php页面,该页面引入一个引导程序文件。该引导文件定义常量,引入其他文件,注册函数等,以及#34; start"系统。引导程序做了两件大事:定义/注册我的自动加载功能,然后通过要求带有异常处理代码的error.php文件对异常处理执行相同的操作。加载引导程序文件后,路由就会发生,系统会继续运行。

我的问题来自以下内容。我在系统中有一个类文件的文件夹。只是具有各种用途的静态方法的类 - 数据库,会话,用户等。所有这些类都会抛出我注册的异常处理程序捕获的各种异常(标准和SPL)。但是,异常处理程序不会捕获Session类的抛出异常。

会话类是一个类(常规,而不是抽象/静态),使用静态方法"扩展" /"替换"默认的PHP会话使用自定义的会话功能,以便将会话数据存储在数据库中。在start()函数中,我使用php会话注册适当的函数" handle"通过session_set_save_handler函数。我也按照php.net的建议调用register_shutdown_function,以确保在应用程序必须突然停止时保存会话数据。

以下是我的会话类的一些代码,它抛出一个PDOExceptoin,因为我的SQL错了 - 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();
    }
}
  1. 如果我删除catch / try,我会得到一个致命的"未被捕获的PDOException"错误。
  2. 如果我尝试使用PDOExceptoin消息在catch块中重新抛出一个新的Exception,那么PHP会在页面底部发出致命的错误消息。它还会吐出异常消息和完整的异常跟踪。
  3. 如果我在catch块中回显异常消息,它将打印出正常且没有致命的未捕获异常错误。
  4. 这是我的异常处理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没有真正按顺序调用它们,只是注册了最后一个函数?

    编辑: 我尝试过以下几点来确认一些事情。

    1. 正在加载error.php文件。如果我在文件中定义一个常量并稍后在index.php文件中将其打印出来,则会打印出来。
    2. 我的bootstrap包含在索引页面后,我可以在index.php中抛出异常,异常按预期执行
    3. 我可以从提供异常的静态数据库函数打印出错误消息,因此try / catch处理在静态函数内部工作

3 个答案:

答案 0 :(得分:0)

在你的set_exception_handler中你有$e ->getLine() ...删除空格......我认为可能会发生的事情是这会导致异常处理程序中出现异常(ErrorException),这就是你的异常看,因为没有什么可以捕获这个例外。

你最好做这样的事情:

$error = "<div style='text-align: center;'>";
$error .= "<h2 style='color: rgb(190, 50, 50);'>".get_class($e)." Occured:</h2>";
$error .= "<table style='width: 800px; display: inline-block;'>";
$error .= "<tr style='background-color:rgb(240,240,240);'><th>Message</th>";
$error .= "<td>".$e->getMessage()."</td></tr>";
$error .= "<tr style='background-color:rgb(230,230,230);'><th>File</th>";
$error .= "<td>".$e->getFile()."</td></tr>";
$error .= "<tr style='background-color:rgb(240,240,240);'><th>Line</th>";
$error .= "<td>".$e->getLine()."</td></tr>";
$error .= "</table></div>";
echo $error;

答案 1 :(得分:0)

} catch (Exception $e) { 
    return $e->getMessage();
}

- 这就是你的经纪人没有抓到任何东西的原因 因为你已经手动抓住了它。

  

如果我删除catch / try,我会收到致命的“未捕获的PDOException”错误。

在抛出异常时检查处理程序是否准备就绪。然后再检查一下。

答案 2 :(得分:0)

不确定这是否有帮助:如果您正在使用命名空间(您应该使用),那么请确保您正在访问正确的Exception类。

要么放入标题

use Exception;

或将反斜杠添加到catch语句

} catch (\Exception $e) {

否则PHP将在您的命名空间内搜索异常类。