PHP中如何捕获$xpath->evaluate触发的非对象属性通知?
这个问题我之前也碰到过,核心原因是你对DOMXPath::evaluate的返回值理解有点偏差——它返回的是DOMNodeList对象,哪怕没有找到任何匹配节点,这个对象依然会被创建,所以直接用if ($sources)判断永远会是true,自然起不到作用;而try-catch抓不到是因为这是E_NOTICE级别的通知,不属于可捕获的异常。
接下来给你几个可行的解决方案,按推荐程度排序:
1. 检查DOMNodeList的length属性(最推荐)
直接通过length属性判断是否有匹配的节点,这是最直观也最优雅的方式:
$doc = new DOMDocument(); $doc->loadHTML($html); $xpath = new DOMXPath($doc); $sources = $xpath->evaluate("//img/@src"); // 先确认有匹配的节点再访问 if ($sources->length > 0) { $src = $sources[0]->value; echo $src; } else { // 这里可以处理没有找到图片的情况 echo "No image source found in the HTML"; }
DOMNodeList的length属性会准确返回列表中节点的数量,大于0就说明有我们要的src属性节点。
2. 用item()方法获取节点并判断
你也可以用item()方法直接取第一个节点,再判断它是否存在:
$doc = new DOMDocument(); $doc->loadHTML($html); $xpath = new DOMXPath($doc); $sources = $xpath->evaluate("//img/@src"); $firstSrcAttr = $sources->item(0); // 确认节点是DOMAttr类型(因为我们取的是属性) if ($firstSrcAttr instanceof DOMAttr) { $src = $firstSrcAttr->value; echo $src; }
当没有匹配节点时,item(0)会返回null,这样就能避免访问不存在对象的属性。
3. 捕获E_NOTICE通知(不推荐,仅用于特殊场景)
如果你确实需要捕获这个通知(比如要记录错误日志),可以通过自定义错误处理器来实现,不过这种方法属于“事后补救”,不如提前检查节点存在性优雅:
// 自定义错误处理函数,专门捕获目标通知 function catchMissingPropertyNotice($errno, $errstr) { if ($errno === E_NOTICE && strpos($errstr, 'Trying to get property of non-object') !== false) { // 这里可以做日志记录或其他处理 error_log("Error accessing image source: " . $errstr); return true; // 返回true表示我们已经处理了这个错误,不再用默认方式输出 } return false; // 其他错误交给默认处理器处理 } // 设置自定义错误处理器 set_error_handler('catchMissingPropertyNotice'); // 你的原有代码 $doc = new DOMDocument(); $doc->loadHTML($html); $xpath = new DOMXPath($doc); $sources = $xpath->evaluate("//img/@src"); $src = $sources[0]->value; echo $src; // 恢复默认错误处理器(可选,如果你之后不需要这个自定义处理器的话) restore_error_handler();
总的来说,最推荐的是第一种方法,从根源上避免错误通知的产生,这也是处理DOM节点操作的常规做法。
内容的提问来源于stack exchange,提问作者Alexander Hörl
相关产品推荐
相关产品推荐

