February 15, 2017 by Christoff Truter PHP
In part 2 we quickly "talked" about having different serialization strategies for our html elements, but as an interim solution, I chose to use the XHTML spec as my standard markup, in this post we're going to decouple our serialization strategy.
Previously we defined two interfaces, IHtmlInnerHtml and IHtmlInnerText, along with an abstract base class, with two abstract methods that we needed to implement in order to tell the serialization code what to do with an element.
Now instead of requiring that our elements implement these interfaces, I created serialization specific classes for each element, I also moved the abstract methods previously defined in the HtmlElement class to an interface of its own.
interface IHtmlElement { function GetAttributes(); function GetTagName(); }
I also removed all serialization implementation from the HtmElement class.
abstract class HtmlElement { public function Render(IHtmlSerializer $serializer = null) { if ($serializer == null) { $serializer = HtmlSettings::$Serializer; } return $serializer->Serialize($this); } }
The Render method now optionally accepts a serialization class (implementing IHtmlSerializer) as parameter, if not supplied it will use default values defined in a newly introduced, HtmlSettings class.
Not going to go into too much detail about the IHtmlSerializer implementations, they basically contain the same code previously located in the HtmlElement class, with some subtle differences (depending on serialization strategy). You can have a look at XHtmlSerializer and HtmlSerializer.
The part I would like to point out is the getSerializer method as seen below.
class XHtmlSerializer implements IHtmlSerializer { ... private function getSerializer($element) { if ($element instanceof HtmlSelectElement) { return new XHtmlSelectSerializer($element); } else if ($element instanceof HtmlOptionElement) { return new XHtmlOptionSerializer($element); } throw new \Exception('No metadata found for element '.get_class($element)); } ... }
class XHtmlSelectSerializer implements IHtmlElement, IHtmlInnerHtml { private $element; public function __construct(HtmlSelectElement $element) { $this->element = $element; } public function GetAttributes() { return [ 'name' => $this->element->GetName(), 'disabled' => ($this->element->Disabled) ? 'disabled' : null ]; } public function GetTagName() { return 'select'; } public function GetInnerHtml() { return $this->element->GetChildren(); } }
class HtmlSelectSerializer implements IHtmlElement, IHtmlInnerHtml { private $element; public function __construct(HtmlSelectElement $element) { $this->element = $element; } public function GetAttributes() { return [ 'name' => $this->element->GetName(), 'disabled' => ($this->element->Disabled) ? '' : null ]; } public function GetTagName() { return 'select'; } public function GetInnerHtml() { return $this->element->GetChildren(); } }
February 17, 2017
PHP drop-down list - Part 4 (Cleaning things up a bit)February 14, 2017
PHP drop-down list - Part 3 (Maintaining State)February 14, 2017
PHP drop-down list - Part 2 (Serialization of elements to HTML)February 14, 2017
PHP drop-down list - Part 1 (Knowing thy elements)February 14, 2017