带有OOP的libxml错误处理程序

时间:2012-04-05 08:35:40

标签: php oop error-handling libxml2

我需要捕获libxml错误。但我想用我的课来做这件事。我知道libxml_get_errors和其他功能。但我需要像libxml_set_erroc_class("myclass")这样的东西,并且在所有情况下,错误都会调用我的班级。我不希望在每次使用后$dom->load(...)创建一些像foreach(libxml_get_errors as $error) {....}这样的结构。你能救我吗?

3 个答案:

答案 0 :(得分:8)

libxml errors主要在阅读或撰写xml文档时生成,因为已完成自动验证。

所以这是你应该集中注意力的地方,你不需要覆盖set_error_handler ..这是一个概念证明

使用内部错误

libxml_use_internal_errors ( true );

示例XML

$xmlstr = <<< XML
<?xml version='1.0' standalone='yes'?>
<movies>
 <movie>
  <titles>PHP: Behind the Parser</title>
 </movie>
</movies>
XML;

echo "<pre>" ;

我想这是你想要实现的一个例子

try {
    $loader = new XmlLoader ( $xmlstr );
} catch ( XmlException $e ) {
    echo $e->getMessage();
}

XMLLoader类

class XmlLoader {
    private $xml;
    private $doc;
    function __construct($xmlstr) {
        $doc = simplexml_load_string ( $xmlstr );

        if (! $doc) {
            throw new XmlException ( libxml_get_errors () );
        }
    }
}

XmlException类

class XmlException extends Exception {

    private $errorMessage = "";
    function __construct(Array $errors) {

        $x = 0;
        foreach ( $errors as $error ) {
            if ($error instanceof LibXMLError) {
                $this->parseError ( $error );
                $x ++;
            }
        }
        if ($x > 0) {
            parent::__construct ( $this->errorMessage );
        } else {
            parent::__construct ( "Unknown Error XmlException" );
        }
    }

    function parseError(LibXMLError $error) {
        switch ($error->level) {
            case LIBXML_ERR_WARNING :
                $this->errorMessage .= "Warning $error->code: ";
                break;
            case LIBXML_ERR_ERROR :
                $this->errorMessage .= "Error $error->code: ";
                break;
            case LIBXML_ERR_FATAL :
                $this->errorMessage .= "Fatal Error $error->code: ";
                break;
        }

        $this->errorMessage .= trim ( $error->message ) . "\n  Line: $error->line" . "\n  Column: $error->column";

        if ($error->file) {
            $this->errorMessage .= "\n  File: $error->file";
        }
    }

}

示例输出

Fatal Error 76: Opening and ending tag mismatch: titles line 4 and title
  Line: 4
  Column: 46

我希望这会有所帮助

由于

答案 1 :(得分:1)

编辑(有错误的混淆异常):

  1. 使用set_exception_handler来捕获全局异常。
  2. 让代码在$dom->load()之类的情况下抛出这些异常。因为libxml似乎没有自己抛出异常,所以你的另一个选择就是在它周围创建一个包装器,在你的代码中使用包装器并让它检查libxml是否有错误并将它们抛到必要的位置例。
  3. 处理“myclass”中的异常。
  4. 请注意,set_exception_handler会抓住所有您的例外情况。

    以下是您可以做的一个示例:

    //inheritance example (composition, though, would be better)
    class MyDOMWrapper extends DOMDocument{
        public function load($filename, $options = 0){
            $bool = parent::load($filename, $options);
            if (!$bool){
                throw new MyDOMException('Shit happens. Feeling lucky.', 777);
            }
        }
    }
    class MyDOMException extends DOMException{
        public $libxml;
    
        public function __construct($message, $code){
            parent::__construct($message, $code);
            $this->libxml = libxml_get_errors();
        }
    }
    class MyDOMExceptionHandler{
        public static function handle($e){
            //handle exception globally
        }
    }
    libxml_use_internal_errors(true);
    set_exception_handler(array('MyDOMErrorHandler', 'handle'));
    
    //global exception handler
    $myDom = new MyDOMWrapper();
    $myDom->load('main.xml');
    
    //when special handling is necessary
    try {
        $myDom = new MyDOMWrapper();
        $myDom->load('main.xml');
    } catch (MyDOMException $e) {   
        //handle or
        throw $e; //rethrow
    }
    

答案 2 :(得分:1)

没有任何设施可以直接执行此操作。您的选择是:

  1. 扩展使用libxml的PHP类,并围绕库存实现包装自定义错误处理逻辑(不是那么好),或者
  2. 编写自己的类,聚合该PHP类的实例并围绕它创建自己的公共接口(更好的是,因为您可以控制公共接口,并且如果PHP类在未来),或
  3. 在解析期间替换全局错误处理程序并在之后将其还原(不是很强大,如果您的代码调用其他代码可能会有问题,但更容易做到)
  4. 解决方案1和2的优势在于,无论如何,它们都不会修改应用程序中任何其他代码的行为。