Вопрос по php, oop – обработчик ошибок libxml с ООП

2

Мне нужно ловить ошибки libxml. Но я хочу использовать свой класс для этого. Я знаю оlibxml_get_errors и другие функции. Но мне нужно что-то вродеlibxml_set_erroc_class("myclass") и в любом случае по ошибке вызовет мой класс. Я не хочу в каждом случае после использования$dom->load(...) создать какую-то конструкцию, какforeach(libxml_get_errors as $error) {....}, Вы можете мне помочь?

Не уверен, почему вы хотите это сделать, ноlibxml_get_errors() вернуть массивLibXMLError Объект ... может быть с дополнительной информацией и кодом .. я могу помочь Baba
Хорошо. У меня есть классы для DOM - Builder и Parser, Calss Validator для проверки XML через XSD. Как я могу реализовать свой собственный обработчик ошибок для этих классов. И мне нужно использовать исключительный класс. ZigZag

Ваш Ответ

3   ответа
7

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

надеюсь, это поможет

Спасибо

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded ZigZag
1

edit (перепутанные исключения с ошибками):

Use set_exception_handler to catch global exceptions. Have your code throw these exceptions in cases like $dom->load(). Because libxml doesn't seem to throw exceptions on its own, your other option is to create a wrapper around it, use the wrapper in your code and have it check libxml for errors and throw them in necessary cases. Handle the exceptions inside "myclass".

Будьте осторожны, чтоset_exception_handler будет ловитьall ваши исключения.

Вот пример того, что вы могли бы сделать:

//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
}
Error: User Rate Limit Exceeded ZigZag
1

extend the PHP class that uses libxml and wrap your custom error handling logic around the stock implementation (not that good), or write your own class that aggregates an instance of that PHP class and create your own public interface around it (better, because you are in control of the public interface and you don't risk problems if the PHP class is extended in the future), or replace the global error handler for the duration of your parsing and restore it afterwards (not as powerful, may be problematic if your code calls into other code, however easier to do)

Преимущество решений 1 и 2 состоит в том, что они не изменяют поведение любого другого кода в вашем приложении, несмотря ни на что.

Похожие вопросы