Facebook
Twitter
Google+
Kommentare
10

Genie oder Wahnsinn: DomExceptionDecorator

Ich glaube, ich habe heute mal wieder Lust eine neue Idee umzusetzen. Und zwar eine Idee für eine neue Kategorie. Ich möchte sie Genie oder Wahnsinn nennen. Ihr kennt wahrscheinlich die Situation, dass ihr ein Problem gelöst habt, aber auf eine ganz abgefahrene Weise. Etwas wo nur ihr drauf hättet kommen können oder halt ungewöhnlich ist.

Ich hatte vor kurzem damit zu kämpfen, dass ein DomDocument beim Laden einer  kaputten XML-Datei Fehler wirft. So richtige PHP-Fehler. Doofe Sache, ich hätte lieber eine Exception, denn dann kann ich darauf reagieren. Da man bei der lib_xml die Möglichkeit hat, die Fehlerverwaltung selbst zu übernehmen, habe ich ein paar Zeilen Code gebaut, mit dem man Exceptions bekommt.


class Base_Xml_Dom_DomDocument_ExceptionDecorator
{
  private $domDocument;

  public function __construct(DOMDocument $domDocument)
  {
    $this->domDocument = $domDocument;
  }

  public function __call($method, $args)
  {
    libxml_use_internal_errors(true);
    call_user_func_array(array($this->domDocument, $method), $args);
    $errors = libxml_get_errors();
    if (count($errors) > 0)
    {
      $message = '';
      $errorOccured = false;
      foreach ($errors as $error)
      {
        /* @var $error LibXMLError */
        if ($error->level >= LIBXML_ERR_ERROR)
        {
          $message .= $error->message . " \n";
          $errorOccured = true;
        }
      }
      libxml_clear_errors();
      libxml_use_internal_errors(false);
      if ($errorOccured)
      {
        throw new Base_Xml_Dom_DomDocument_Exception($message);
      }
    }
  }

  public function __set( $key, $value )
  {
    $this->domDocument->$key = $value;
  }

  public function __get( $key )
  {
    return $this->domDocument->$key;
  }
}

Die Implementierung löst mein Problem mit dem Laden einer XML-Datei. Dabei wirft es mit jedes mal eine „saubere“ Exception, wenn ein Fehler auf diesem Objekt auftritt. Leider löst es noch nicht das Problem, dass die vom DomDocument erzeugten Dom-Kindklassen das alter Verhalten haben. Aber da kann man ja auch noch dran drehen.

Also los. Einfach nur einen Kommentar hinterlassen mit Genie oder Wahnsinn.

Über den Autor

Nils Langner

Nils Langner ist der Gründer von "the web hates me" und auch der Hauptautor. Im wahren Leben leitet er das Qualitätsmanagementteam im Gruner+Jahr-Digitalbereich und ist somit für Seiten wie stern.de, eltern.de und gala.de aus Qualitätssicht verantwortlich. Nils schreibt seit den Anfängen von phphatesme, welches er ebenfalls gegründet hat, nicht nur für diverse Blogs, sondern auch für Fachmagazine, wie das PHP Magazin, die t3n, die c't oder die iX. Nebenbei ist er noch ein gern gesehener Sprecher auf Konferenzen. Herr Langner schreibt die Texte über sich gerne in der dritten Form.
Kommentare

10 Comments

  1. Die Lösung finde ich recht schick. Hässlicher finde ich, dass bei Nutzung von __call und Konsorten die IDE keine Hilfe mehr ist und mir nichts zu den Objektmethoden vorschlagen kann. Darum habe ich mir die save- und load-Methoden weggekapselt, das eigentliche DOMDocument bleibt unverändert.

    Reply
  2. Also ich würde ja eher zu Wahnsinn tendieren (o; Schreib dir doch lieber einen allgemeinen Error-Handler. Dieser wirft dann bei jedem PHP-Error eine Exception.

    Wenn du aber bei deiner jetzigen Lösung festhalten willst kannst du auch die Methode DOMDocument::registerNodeClass nutzen um die DOMAttr und DOMNode Klassen zu dekorieren.

    Reply
  3. @Hannes: Das ist mir klar. Verbessere mich, wenn ich falsch liege, aber ein solcher Typhint hilft der IDE auch nicht weiter und kann mir keine Hints zu den Methoden der Klasse geben, die an die innere DOMDocument-Instanz weiter delegiert werden.

    Reply
  4. @Martin das ist so nicht ganz richtig. Zumindest im ZendStudio (wohl auch im PDT) genügt es die Methoden im DocBlock der Klasse zu deklarieren zb.
    * @method mixed findBy*(mixed $value) magic finders; @see __call()
    * @method mixed findOneBy*(mixed $value) magic finders; @see __call()

    Reply
  5. Etwas ähnliches habe ich die Tage doch schon gesehen. Ich sehe jetzt nicht wirkliche eine Innovation. Etwas ähnliches wurde ja bereits in den User-Comments von DOMDocument::schemaValidate() in 2006 umgesetzt. OK, da wird gegen ein Schema, nicht die XML geprüft und das ganze ist nicht in OOP, aber ansonsten ähnlich.

    Deshalb würde ich sagen, weder Genie noch Wahnsinn. :-)

    Reply
  6. Also ich würde ja eher zu Wahnsinn tendieren (o; Schreib dir doch lieber einen allgemeinen Error-Handler. Dieser wirft dann bei jedem PHP-Error eine Exception.

    Diese Aussage kann ich so nicht bestätigen.
    Wenn ich mich nicht völlig irre, können auf diese Weise nur user-defined Errors zu Exceptions umgewandelt werden.

    Systemfehler sind nicht zu Exceptions umwandelbar! Um welche Art von Fehlern es sich hier handelt, kann ich nicht sagen, da ich mich damit nicht beschäftigt habe. Schätze aber mal, E_USER_ERRORS und somit tatsächlich eleganter wie von dir genannt (Christian) lösbar.

    Reply
  7. @Christian: [Zitat]:“Also ich würde ja eher zu Wahnsinn tendieren (o; Schreib dir doch lieber einen allgemeinen Error-Handler. Dieser wirft dann bei jedem PHP-Error eine Exception.“
    Diese Aussage kann ich so nicht bestätigen.
    Wenn ich mich nicht völlig irre, können auf diese Weise nur user defined Errors zu Exceptions umgewandelt werden.

    Systemfehler sind nicht zu Exceptions umwandelbar! Um welche Art von Fehlern es sich hier handelt, kann ich nicht sagen, da ich mich damit nicht beschäftigt habe. Schätze aber mal, E_USER_ERRORS und somit tatsächlich eleganter wie von dir genannt (Christian) lösbar.

    Ich wollte nur darauf hinweisen, dass die von dir genannte Lösung nicht generell verwendbar ist.

    Reply
  8. Die Lösung hat leider ein großes Problem:

    (Base_Xml_Dom_DomDocument_ExceptionDecorator instanceof DomDocument) ist false und damit kannst Du die Klasse nicht dort verwenden, wo die Applikation ein DomDocument verwendet und das z.B. mit Type Hints validiert.

    Reply

Leave a Comment.

Link erfolgreich vorgeschlagen.

Vielen Dank, dass du einen Link vorgeschlagen hast. Wir werden ihn sobald wie möglich prüfen. Schließen