Best practice to create XML messages with DOMDocument class in PHP I want to create XML messages for webservice communication. These messages should be created from a pool of reusable elements. Therefore I have created different classes. A "factory" class, that only returns a message class. An element class, that consists of the reusable parts and the message classes that are the blueprints for the desired XML messages.

My code delivers the expected result, but I'm looking for a best practice. Especially a way to get rid of rewriting the same save() and __construct method in every of the message classes.

Update:


  I have improved my example and moved the root property and the
  save() method from the message classes to the Elements class. I
  also changed the name of the method from save to getMessage as
  there is a DOMDocument method with the same name. Due to these
  changes I have little less redudant code. I still don't know if it is
  good practice, particularly to use the "grandparent" methods in the
  message classes.


// class to create webservice messages
class Messages{

    private function __construct(){}

    public static function get($type) {
        //some error handling if class not exists
        return new $type;
    }
}

// message no.1
class Message_1 extends Elements{

    public function __construct() {
        parent::__construct();
        $this-&gt;root = $this-&gt;createElement("message1");
    }

    public function add_anotherElement(){
        $this-&gt;root-&gt;appendChild($this-&gt;add_anotherElementBlock("foo", "bar"));
    }

    public function add_element(){
        $this-&gt;root-&gt;appendChild($this-&gt;add_someElementBlock("foo", "bar"));
    }
}

// message no.2
class Message_2 extends Elements {

    public function __construct() {
        parent::__construct();
        $this-&gt;root = $this-&gt;createElement("message2");
    }

    public function add_elements(){
        $this-&gt;root-&gt;appendChild($this-&gt;add_anotherElementBlock("foo", "bar"));
        $this-&gt;root-&gt;appendChild($this-&gt;add_someElementBlock("foo", "bar"));
    }

}

// message no.3
class Message_3 extends Elements {

    public function __construct() {
        parent::__construct();
        $this-&gt;root = $this-&gt;createElement("message3");
    }

    public function add_element(){
        // unique Element
        $this-&gt;root-&gt;appendChild($this-&gt;createElement("foo", "bar"));
    }

}

// reusable elements
class Elements extends DOMDocument{

    protected $root;


    protected function add_someElementBlock($foo, $bar) {
        $node = $this-&gt;createElement("root");

        $attr = $this-&gt;createAttribute("id");
        $attr-&gt;value = $foo;
        $node-&gt;appendChild($attr);

        $subnode = $this-&gt;createElement("sub",$bar);

        $node-&gt;appendChild($subnode);

        return $node;
    }

    protected function add_anotherElementBlock($foo, $bar) {
        $node = $this-&gt;createElement("anotherRoot");

        $subnode = $this-&gt;createElement("anotherSubNode",$bar);
        $attr = $this-&gt;createAttribute("anotherAttribute");
        $attr-&gt;value = $foo;
        $subnode-&gt;appendChild($attr);

        $node-&gt;appendChild($subnode);

        return $node;
    }

    public function getMessage(){
        return $this-&gt;saveXML($this-&gt;root);
    }
}

$message1 = Messages::get('Message_1');
$message1-&gt;add_element();
$message1-&gt;add_anotherElement();

$message2 = Messages::get('Message_2');
$message2-&gt;add_elements();

$message3 = Messages::get('Message_3');
$message3-&gt;add_element();

//********************************************
echo "&lt;pre&gt;";
print_r(htmlentities($message1-&gt;getMessage()));
echo "&lt;/pre&gt;";
echo "&lt;hr /&gt;";
echo "&lt;pre&gt;";
print_r(htmlentities($message2-&gt;getMessage()));
echo "&lt;/pre&gt;";
echo "&lt;hr /&gt;";
echo "&lt;pre&gt;";
print_r(htmlentities($message3-&gt;getMessage()));
echo "&lt;/pre&gt;";
Your message classes currently have two responsibilities: representing an application logic message and transforming itself into a representation. If you want to add other ways of serialization you have to modify the message classes itself.

The message classes only should represent the message while some other facility should be responsible for serializing your messages into xml. This keeps the interface of your message classes clean (not inheriting all those methods from DOMDocument) and allows to easily add other serialization formats. 

This particular situation wants a strategy pattern: a dedicated MessageXmlSerializer takes a message, creates the surrogate DOMDocument and itself delegates the serialization of the message further to specialized classes for each message:

&lt;?php

class MessageXmlSerializer {

    private $messageSerializers;

    public function serialize(Message $message) {
        $node = $this-&gt;createDocumentContainer();

        foreach ($this-&gt;messageSerializers as $serializer) {
            if ($serializer-&gt;canHandle($message)) {
                $node-&gt;appendChild($serializer-&gt;serialize($message));
            }
        }
    }

    protected function createDocumentContainer() {
        $node = new DOMDocument();
        // Do your intialization here
        return $node;
    }
}


The dedicated serializers are rather simple. Of course they all share a common interface:

interface MessageSerializer {
    public function canHandle(Message $message);

    public function serialize(Message $message);
}


And finally the serializer specialized on serializing Message_1

class MessageOneSerializer implements MessageSerializer {
    public function canHandle(Message $message) {
        return $message instanceof Message_1;
    }

    public function serialize(Message $message) {
        // create your node here and return it
    }
}


So far the basic concept. Now new message types can easily be added and serializiation the messages itself are separated. Of course, as for any pattern, this concept can (should) be extended and adjusted to your needs.