PHP 5.4 - My First Traits Project

Later this month I’m going to start migrating my personal framework over to 5.4 (I intend to eventually publicly release it - but work keeps delaying things). One of the first structural changes I am going to play with are traits. I’d like to discuss what I intend here because the concepts of traits and grafting are still new to me.

For reference - The PHP Documentation on Traits

One area in my project I see this as useful is the view section of my code. Currently all of my template handling classes descend from the responder class. While things aren’t ugly, they aren’t as straight forward as I’d like. Here’s an abbreviated look at the current inheritance tree sufficient to illustrate the problem.

abstract Responder extends ArrayObject

HTMLResponder extends Responder
PageResponder extends HTMLResponder
JavascriptResponder extends Responder
StyleResponder extends Responder

Here’s the thing. HTMLResponders parse phtml templates into strings - they do not usually need to have a full page response. I’m inclined to think not carrying that ability will - at the least - make the code easier to read.

So this is my thoughts on a replacement.

trait HTTPResponder -> holds methods for transmitting the data over the HTTP protocol, which is the most typical. Eventually I can write a SAPIResponder and have both fulfill the requirements of a Responder interface.

Template -> A class for handling html templates
TextOut -> A class for Text outputting - foundational to javascript and css responses since neither have any phtml template parsing responsibility.

HTMLResponder extends Template uses HTTPResponder -> for normal request responses.
XMLResponder extends Template uses HTTPResponder -> for AJAX responses
JavascriptResponder extends TextOut uses HTTPResponder -> for straight JS responses.
StyleResponder extends TextOut uses HTTPResponder -> for CSS

FormTemplate extends Template -> A template for form object management. If it’s part of a larger page we use this object, otherwise it’s sister:

FormResponder extends Template uses HTTPResponder

Thoughts?

Note - part of the reason for this (which lastcraft influenced me heavily on) is to further reduce the scope of an individual code block. During testing traits can be bound to mock objects to be tested on their own, then the tests of the objects composed of the traits can be ran. The goal is to keep the dependency chain as short as possible.

Jury is still out on traits imo.
They’re stateless nature and my belief that getters and setters are evil, are at odds with one another.

So end up with a collection of traits which you can mix and match to provide an implementation for an interface.


trait UTF8Text
{
	function text($text)
	{
		return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
	}
}

trait HTMLAttributes
{
	function attributes(array $attributes = null)
	{
		$r = '';
		if ($attributes)
			foreach($attributes as $name => $value)
			{
				if (false === $value || null === $value)
					continue;
				$r .= ' '.$name;
				if (true !== $value)
					$r .= '="'.$this->text($value).'"';
			}
		return $r;
	}
	
	abstract function text($text);
}

trait XMLAttributes
{
	function attributes(array $attributes = null)
	{
		$r = '';
		if ($attributes)
			foreach($attributes as $name => $value)
			{
				if (false === $value || null === $value)
					continue;
				$r .= ' '.$name.'="'.$this->text(true === $value ? $name : $value).'"';
			}
		return $r;
	}
	
	abstract function text($text);
}

interface Helper
{
	function text($text);
	function attributes(array $attributes = null);	
}

class HTMLHelper implements Helper
{
	use UTF8Text, HTMLAttributes;
}

class XMLHelper implements Helper
{
	use UTF8Text, XMLAttributes;
}

So I find it hard to construct any thoughts on your proposed design when I’m thinking traits are seemingly pretty limited*. And also why haven’t responded til now.

*Assuming don’t like using getters & setters.

I have to say that I find traits to be an interesting addition to the php toolbox. But I also have mixed feelings on the subject. On one hand I see the potential, the ability to package functionality to be deploy horizontally across objects seems like a god-send on first glance. But the aged coder in me raises red flags stating that single inheritance encourages “good” oop design by forcing us to think vertically to create elegant hierarchies.

I agree that the jury is still out on this and only time will tell. It will be quite awhile before I allow traits onto production servers. Like all other vetted php features, it will need time to prove its worth.