PHP PDO 错误处理暂停执行

PHP PDO error handling halting execution

我是 PHP 的新手,来自 ASP,我很难理解错误处理如何与 PHP 和 PDO 一起工作。这是我正在进行的...

PDO 设置为:

PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION

我正在对 PHP 页面进行 AJAX 调用以处理一些数据并使用 PDO 将其保存到 MySQL。我在 try catch 中有我的数据库脚本,如下所示:

function processStuff(){
    try {
       $sth = $db->prepare( query );
       $sth->execute();
    } catch (PDOEXCEPTION $e){
        //log error
    }

    //if no error
    return array(some json);
}

假设发生了一些不好的事情,我收到如下错误:

Error: exception 'PDOException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'field' cannot be null' in C:\filepath:202

发生的事情是错误正在暂停脚本,从而导致调用页面挂起。 AJAX 正在等待 JSON 响应,该响应将表明它是成功还是失败。但是因为它挂起,所以没有得到响应,所以我没有机会向用户显示出现错误。

我还有一个自定义错误处理函数:

function errorHandler($errno, $errstr, $errfile, $errline) {
    //log errors
}

set_error_handler("errorHandler")

可以记录错误。但是,由于我是新手,我不确定如何在 try/catch.

中使用它

所以我的问题是,如何在发生 PDO 异常时记录错误并确保脚本继续处理,以便带有 AJAX 的调用页面不会挂起。

围绕类似问题的所有其他答案都假定了我似乎还不具备的知识水平。我不清楚我是否应该抛出一个错误被捕获,或者它是否被自动抛出。如果 PDO 自动抛出它,我如何在 catch 中调用我的错误处理程序?我会使用:

errorHandler();

如果我切换到 ERRMODE_SILENT,我相信这会继续处理,我如何检测错误以便将其抛出?

我确信有一些我只是不了解其工作原理的基本概念。代码很棒,但非常感谢任何解释。

谢谢。

更新: 这是实际的 try 块:

        try {
            $sth = $dbh->prepare ("INSERT INTO email_validation (email, val_code) VALUES (:a1, :a2)");
            $sth->bindParam (":a1", $email);
            $sth->bindParam (":a2", $gencode);
            $sth->execute ();
        } catch (PDOEXCEPTION $e) {
            $err = true;
            $errmsg = date("F j, Y, g:i a") . "\n" . ERR_URL . "\n" . $e . "\n\n";
            error_log($errmsg,3,ERR_LOG_PATH_INT);
        }

AJAX 看起来像这样:

    $.post('Functions/AJAX-new-account.php', $('form').serialize(), function(data) {
        var c = data.check;
        if(c==1){
            //process client side stuff here
        }else{
            //----Ooops there was an error-----//
            //show error to client
        };
        return false;
    },"json");

我想 JSON 正在写入,但我不明白为什么我的 AJAX 中似乎没有到达 }else{ 并且页面似乎停滞了。

另一个更新:所以我刚刚尝试了

trigger_error("blah blah");

在 catch 块中,它停止挂起。 errorHandler 似乎正确处理了错误,虽然我的 AJAX 处理错误,但它确实停止了挂起。这是处理此问题的正确方法,还是有更好的方法?

你在这里有几个问题,我会尽量一一解答。

If I switched to ERRMODE_SILENT, which I believe would continue the processing, how do I detect the error in order to throw it to the catch?

在这种情况下,您不需要使用 try/catch,而是需要一个 if 语句来检查 PDO 错误代码,例如if ($db->errorCode() !== null)(请参阅 PHPDoc 了解 PDO Error Handling) where you would log the error, perhaps set the HTTP Response Code 到您期望从 Javascript 获得的内容。

Why is my AJAX request hanging after this failure?

我怀疑您的页面实际上并没有挂起;相反,由于某种原因,没有 JS 被执行。在您的第一次尝试中,您会得到一个 500 错误代码,它不会触发您提供给 $.post.success() 函数。为了在这种情况下看到问题,您需要向 AJAX 请求添加 .fail() 回调。

一旦您切换到使用 trigger_error,由于没有抛出异常,将返回 200 OK。我不确定 "my AJAX processed it incorrectly".

是什么意思

Is this a correct way to handle this, or is there a better way?

这在很大程度上取决于偏好。 PDO 异常对我来说应该是非常罕见的,因为我在将数据发送到数据库之前正在处理和验证数据。在您的情况下,Column 'field' cannot be null 是您应该事先检查的一个很好的例子。

如果确实发生 PDO 异常,我会尝试优雅地处理它——这意味着 catch 处理它,记录错误,将 HTTP 响应代码设置为合理的值(可能 400 Bad Request会做),并返回带有错误消息的结果。从 Javascript 开始,我将有一个 .fail 方法来分析错误结果并显示适合用户的内容。将成功和失败案例的方法完全分开是一个很好的设计原则,有助于避免代码混乱。

希望本文对您有所帮助。