为什么这个错误处理函数会导致domdocument()挂起?

时间:2011-08-20 02:00:18

标签: php error-handling domdocument

我包含这个简单的错误处理函数来格式化错误:

date_default_timezone_set('America/New_York');

// Create the error handler.
function my_error_handler ($e_number, $e_message, $e_file, $e_line, $e_vars) {

    // Build the error message.
    $message = "An error occurred in script '$e_file' on line $e_line: \n<br />$e_message\n<br />";

    // Add the date and time.
    $message .= "Date/Time: " . date('n-j-Y H:i:s') . "\n<br />";

    // Append $e_vars to the $message.
    $message .= "<pre>" . print_r ($e_vars, 1) . "</pre>\n<br />";

    echo '<div id="Error">' . $message . '</div><br />';

} // End of my_error_handler() definition.

// Use my error handler.
set_error_handler ('my_error_handler');

当我将其包含在带有以下

的脚本中时
$dom = new DOMDocument();
$dom->loadHTML($output);
$xpath = new DOMXPath($dom);

并解析一个网页(在这种情况下,http://www.ssense.com/women/designers/all/all/page_1,我有权解析)我收到错误,如

AN ERROR OCCURRED IN SCRIPT '/HSPHERE/LOCAL/HOME/SITE.COM/SCRIPT.PHP' ON LINE 59: 
DOMDOCUMENT::LOADHTML(): HTMLPARSEENTITYREF: NO NAME IN ENTITY, LINE: 57

AN ERROR OCCURRED IN SCRIPT '/HSPHERE/LOCAL/HOME/SITE.COM/SCRIPT.PHP' ON LINE 59: 
DOMDOCUMENT::LOADHTML(): TAG NAV INVALID IN ENTITY, LINE: 58

有许多错误,页面永远不会完成加载。但是,如果我不包含此错误处理程序,则行

$dom->loadHTML($output);

不会抛出任何错误,我会在几秒钟内得到我期望的结果。我假设错误处理程序正在捕获与loadHTML()相关的警告,这些警告未以其他方式报告。 (即使我使用

@$dom->loadHTML($output);

它仍会报告错误。)我如何修改错误处理程序以适应对loadHTML()的调用,或以其他方式解决此问题?

2 个答案:

答案 0 :(得分:3)

您要加载的网页包含许多错误。例如,&而不是HTML中的&amp;实体。

PHP DOM使用libxml,因此要禁用插入行的所有错误:

libxml_use_internal_errors(true);

稍后您可以使用libxml_get_errors()获取解析错误列表。

答案 1 :(得分:2)

导致错误的不是自定义错误处理程序。

我在没有自定义错误处理程序的情况下运行了以下代码:

$output = file_get_contents("http://www.ssense.com/women/designers/all/all/page_1");
$dom = new DOMDocument();
$dom->loadHTML($output);
$xpath = new DOMXPath($dom);

当我运行它时,我收到了大量类似于错误处理程序中的警告消息。

我认为您遇到的问题只是您的错误处理程序报告了PHP默认情况下未报告的错误。

默认情况下,错误报告级别由您的php.ini设置决定,但可以使用error_reporting()功能覆盖。设置自己的错误处理程序时,必须自己确定要处理的报告级别。您的错误处理程序将在每个错误和通知上调用,因此您将输出所有的错误消息,除非您明确检查针对当前{{1}生成的错误等级。

请记住,使用error_reporting()错误抑制运算符只是为该行设置@的简写。例如,这一行:

error_reporting(0)

简单地说明以下内容:

@$dom->loadHTML($output);

由于在使用自定义处理程序时完全绕过了正常的PHP错误报告,因此使用$errorLevel = error_reporting(0); $dom->loadHTML($output); error_reporting($errorLevel); 运算符是没有意义的,因为完全忽略了当前的@级别。您必须将自定义代码写入错误处理程序以检查当前error_reporting()级别并相应地处理它,例如:

error_reporting()

我的假设是,当不使用自定义错误处理程序时,PHP只是默认为function my_error_handler() { if (error_reporting() == 0) { return; // do nothing when error_reporting is disabled. } // normal error handling here } 级别,该级别低于生成的错误。

如果您将error_reporting()添加到代码顶部,即使您没有启用自定义错误处理程序,也会看到相同的错误。