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

标签 php exception exception-handling error-handling try-catch

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

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 block 并将所有代码移动到新的 if block 中。这似乎不是一种明智的做事方式。

我一直在阅读有关 try/catch 的内容,并一直在考虑将我的所有代码放在一个 try 语句中,然后让代码在没有任何 if/else block 的情况下按顺序运行,如果出现故障,则抛出异常。根据我的阅读,这将停止执行并使其直接跳转到 catch block (就像失败的 if 语句将转到 else block ),然后我可以在那里输出错误消息。但这是可接受的或标准的做法吗?

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

感谢您的建议!

最佳答案

有很多方法可以解决这个问题,坦率地说,没有一种方法本质上是“正确的”。

您必须自己决定哪种方法对您来说更“舒适”——它始终取决于您的偏好(尽管您应该避免某些技术,并且有充分的理由)。

这在很大程度上取决于您如何拆分逻辑,但是我倾向于将所有可以返回非 fatal error 的代码包含在函数中,并使用所述函数的返回值来指示存在错误。

对于 fatal errors我倾向于使用异常(使用 try-catch block )。

现在要明确一点:

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

非 fatal error (使用函数返回)

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

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函数本身就是一个例子——it will return .

Returns a file pointer resource on success, or FALSE on error.


fatal error (使用异常 - 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();
}

不要过度使用异常!

无论你做什么,都不要使用异常来检查你可以从中恢复的东西。阅读 on another question (完全归功于 Anton Gogolev 对此的很好解释,以及其他回答者)为什么会这样。

进一步阅读

现在,要学习如何处理错误,最好的方法莫过于尝试几件事,看看什么对你有好处。您可能会发现以下内容很有用:

希望这会有所帮助:)

关于php - 处理 php 页面错误的最佳方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11894115/

相关文章:

c++ - 为什么 pthread_exit 会抛出被省略号捕获的东西?

java - 为什么 multi-catch RuntimeException 可以编译,而 multi-catch Exception 不编译?

php - 从多级数组中获取数据

javascript - + 使用 javascript 传递值时缺少符号

java - 使用私有(private) setter 或在构造函数中工作

java - 在 Java 中进行多个异步调用时如何忽略失败的 CompletableFuture 调用?

c# - .NET - 实现 "catch all exceptions handler"的最佳方法是什么

C++:对象切片和异常

javascript - jquery如何显示不同颜色的按钮

php - 如何更新重复条目中的单行