现在我的网页看起来像这样:
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应用程序中处理错误的最佳方法是什么,致命与否?我不想只是死于空白屏幕,因为这将是非常友好的用户,而是想在页面正文中输出一条消息,仍然允许页眉和页脚显示。
感谢您的建议!
答案 0 :(得分:34)
有很多方法可以解决这个问题,坦率地说,没有一种方法可以解决这个问题。
你必须自己决定哪种方法对你来说更“舒服” - 它始终是一种偏好(虽然你应该避免使用某些技术并且有充分的理由)。
它将高度依赖于您如何拆分逻辑,但是我倾向于包含所有可以在函数内返回非致命错误的代码,并使用所述函数的返回值来指示存在错误。
对于fatal errors,我倾向于使用例外(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
本身就是一个例子 - it will return。
成功时返回文件指针资源,错误时返回FALSE。
如果你有一段需要执行的代码,因为它正是用户想要的(例如从数据库中读取所有新闻并将其显示给用户),你可以使用异常。让我们举一个简单的例子 - 用户访问了他的个人资料,并希望看到他得到的所有消息(现在让我们假设它们以纯文本形式存储)。您可能具有以下功能:
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 以获得关于此问题以及其他答案人员的非常好的解释)。为什么会出现这种情况。
现在没有更好的方法来学习如何处理错误,而不是尝试几件事情,看看什么对你有好处。您可能会发现以下内容有用:
trigger_error()
函数,我没有提及,因为我没有使用它,也不太了解它,但显然它真的很有用。 这是一个特别好的阅读。 希望这会有所帮助:)
答案 1 :(得分:6)
PHP有一个内置类ErrorException,用于将PHP errors转换为异常,如果未处理,则会自然停止执行。
异常改进了错误处理机制(try catch)和更好的调试信息(堆栈跟踪)。
将此信息包含在执行路径的最顶层(配置,或首先包含所有代码的内容):
set_error_handler(function($nNumber, $strMessage, $strFilePath, $nLineNumber){
throw new \ErrorException($strMessage, 0, $nNumber, $strFilePath, $nLineNumber);
}, /*E_ALL*/ -1);
虽然PDO支持抛出异常,但默认情况下它是关闭的,您必须启用它:
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
如果使用MySQL,您还需要在默认情况下不设置必填字段和许多其他错误/警告的错误:
$pdo->exec("SET sql_mode = 'STRICT_ALL_TABLES'");
可以像许多其他编程语言一样处理异常
try
{
echo $iAmAnUndefinedVariable;
}
catch(\Throwable $exception)
{
/*[...]*/
}
验证内容时,只需抛出异常:throw new Exception("Missing URL variable userId!");
如果PHP有一天从遗留的error reporting事件中彻底解决并且默认情况下抛出异常(弃用error_reporting()并更改默认值),那将是很好的。
答案 2 :(得分:5)
这更加优雅和可读。
try
{
if($_GET['something'] != 'somevalue')
{
throw new Exception ('something is not a valid value');
}
$output .= 'somecode';
// make a DB query, fetch a row
//...
$row = $stmt->Fetch(PDO::ASSOC);
if($row == null)
{
throw new Exception ('the row does not exist.');
}
$output .= 'morecode';
if(somethingIsOK())
{
$output .= 'yet more page output';
}
else
{
throw new Exception ('something is most definitely not OK.');
}
echo $output;
}
catch (Exception $e)
{
echo $e->getMessage();
}
答案 3 :(得分:2)
使用try-catch
是您可以使用的最简洁的解决方案之一。
我做了一个示例,在发生错误时仍然显示页眉和页脚,使用转换为try-catch
格式的代码:
<强> PHP:强>
<?php
try {
$output = array();
if($_GET['something'] != 'somevalue') throw new Exception('something does not have a valid value.');
$output[] = 'Some Code';
$row = mt_rand(0, 10) < 5 ? null : mt_rand(0, 100);
if($row === null) throw new Exception('The row does not exist.');
$output[] = $row;
if(!somethingIsOK()) throw new Exception('Something is most definitely not OK.');
$output[] = 'Yet more page output';
} catch(Exception $e) {
$output[] = 'Error: ' . $e->getMessage(); // To show output and error
$output = array('Error: ' . $e->getMessage()); // To only show error
}
function somethingIsOK() {
return mt_rand(0, 10) < 5;
}
?>
<强> HTML:强>
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8" />
<title>PHP Error test</title>
<style type="text/css">
body {
background: #eee;
text-align: center
}
#content {
padding: 60px
}
#header {
padding: 30px;
background: #fff
}
#footer {
padding: 10px;
background: #ddd
}
</style>
</head>
<body>
<div id="header">Header</div>
<div id="content">
<?php echo implode('<br />', $output); ?>
</div>
<div id="footer">Footer</div>
</body>
</html>
<强>参考文献:强>
答案 4 :(得分:1)
查询的PDO错误异常处理,实际上所有代码都应该运行:
try{
}
catch{
}
finally{
}
这样做的原因是,当您可以粗略地查明冗长脚本中发生错误的位置时,它会使调试变得更加容易
答案 5 :(得分:0)
创建错误处理程序(set_error_handler)并在其中抛出异常 它将有助于支持例外的功能。
答案 6 :(得分:0)
使用错误处理功能正确处理PHP错误和警告。 (参见示例here)
PHP中错误处理的最佳方法是, 您可以通过在php文件的顶部添加此行来停止所有错误报告 -
error_reporting(0);
//OR
error_reporting('E_ALL');
// Predefined Constant
使用函数在PHP中进行错误处理:
上面列出的所有函数都用于PHP中的错误处理。
答案 7 :(得分:-3)
如果您正在搜索看起来很漂亮且可行的代码结构,那么您可以使用我一直使用的whitelist
方法。例如 - 验证$_GET
变量:
$error = false;
if(!isset($_GET['var']))
{
$error = 'Please enter var\'s value';
}
elseif(empty($_GET['var']))
{
$error = 'Var shouldn\'t be empty';
}
elseif(!ctype_alnum($_GET['var']))
{
$error = 'Var should be alphanumeric';
}
//if we have no errors -> proceed to db part
if(!$error)
{
//inserting var into database table
}
所以,就是它,只有2个if/elseif
块,没有嵌套