一尘不染

处理php页面上的错误的最佳方法?

php

现在我的页面看起来像这样:

if($_GET['something'] == 'somevalue')
{
    $output .= 'somecode';

    // make a DB query, fetch a row
    //...
    $row = $stmt->Fetch(PDO::ASSOC);

    if($row != null)
    {
        $output .= 'morecode';

        if(somethingIsOK())
        {
            $output .= 'yet more page output';
        }
        else
        {
            $error = 'something is most definitely not OK.';
        }
    }
    else
    {
        $error = 'the row does not exist.';
    }
}
else
{
    $error = 'something is not a valid value';
}

if($error == '') // no error
{
    //display $output on page
}
else // an error
{
    // display whatever error occurred on the page
}

我的工作方式可行,但是对于显而易见的事情却非常繁琐和乏味:假设我在代码中间的某个地方调用了一个函数,或者想检查变量的值,或者验证数据库查询返回有效结果,如果失败,我想输出错误?我将不得不制作另一个if
/ else块,并将所有代码移到新的if块内。这似乎不是一种明智的处理方式。

我一直在阅读有关try / catch的内容,并一直在考虑将我的所有代码放入try语句中,然后让代码按顺序运行,而没有任何if /
else块,如果发生故障,则仅引发异常。从我所读的内容来看,这将暂停执行并使它直接跳转到catch块(就像一条失败的if语句将进入else块一样),然后我可以在其中输出错误消息。但这是可接受的还是标准的做法?

在构建并输出HTML页面的php应用程序中,处理致命或致命错误的最佳方法是什么?我不想只是死于空白屏幕,因为这对用户非常不友好,而是想在页面正文中输出一条消息,同时仍然允许显示页眉和页脚。

谢谢你的建议!


阅读 180

收藏
2020-05-29

共1个答案

一尘不染

有很多方法可以解决此问题,坦率地说,这些方法本质上都不是“正确的”。

您将需要自己决定哪种方法更适合您-它始终是首选参数(尽管出于某些原因,您应该避免使用某些技术)。

这在很大程度上取决于您如何拆分逻辑,但是我倾向于将所有可以返回非致命错误的代码封装在一个函数中,并使用该函数的返回值指示存在错误。

对于致命错误,我倾向于使用异常(带有try-catch块)。

现在只是要清楚:

  • 非致命错误是您可以从中 恢复 的错误-意味着即使出现问题,仍然可以执行一些代码并生成一些有价值的输出。例如,如果您想使用NTP协议获取当前时间,但服务器没有响应,则可以决定使用本地time功能,并仍然向用户显示一些有价值的数据。
  • 致命错误是您将无法从中 恢复 的错误-意味着确实发生了非常糟糕的事情,唯一可以做的就是告诉您的用户该页面无法执行所要求的操作。例如,如果您正在从数据库中获取一些数据并得到了SQL Exception-没有有价值的数据要显示,那么您只能将此通知用户。

非致命错误(使用函数返回)

使用函数返回作为处理非致命问题的一种很好的示例是,当函数 不是 页面 的主要目标时
,它试图在页面上显示某些文件的内容(例如,一个在每页上显示从文本文件中提取的徽章的功能-我知道这很可取,但请耐心等待)。

function getBadge($file){
    $f = fopen($file,'r');
    if(!$f){
        return null;
    }
    .. do some processing ..
    return $badges;
}

$badges = getBadges('badges.txt');
if(!$badges){
    echo "Cannot display badges.";
} else {
    echo $badges;
}
.. carry on doing whatever page should be doing ..

实际上,函数fopen本身就是一个例子- 它会返回

成功返回文件指针资源,错误返回FALSE。


致命错误(使用异常-try-catch)

当因为您正是用户想要的而 需要执行 某些代码时(例如,从数据库中读取所有新闻并将其显示给用户),则可以使用异常。让我们举一个简单的例子-
一个用户访问了他的个人资料,想查看他收到的所有消息(现在假设它们以纯文本格式存储)。您可能具有以下功能:

function getMessages($user){
    $messages = array();
    $f = fopen("messages_$user.txt","r");
    if(!$f){
        throw new Exception("Could not read messages!");
    }
    ... do some processing ...
    return $messages;
}

并像这样使用它:

try{
    ..do some stuff..
    $messages = getMessages($_SESSION['user'])); //assuming you store username in $_SESSION
    foreach($messages as $msg){
        echo $msg."<br/>";
    }
} catch(Exception $e){
    echo "Sorry, there was an error: ".$e->getMessage();
}

现在,如果您有一个可以执行所有其他代码的“顶级”脚本,这可能会派上用场。这意味着,例如,index.php您将只有:

try{
    .. execute some code, perform some functions ..
} catch(Exception $e){
    echo "Sorry, there was an error: ".$e->getMessage();
}

不要滥用异常!

无论您做什么,都不要使用异常作为检查可以恢复的东西的方式。

2020-05-29