Ruby
Article
By Mal Curtis

Confessions of a Converted PHP Developer: Mixing Like a Baker

By Mal Curtis
Help us help you! You'll get a... FREE 6-Month Subscription to SitePoint Premium Plus you'll go in the draw to WIN a new Macbook SitePoint 2017 Survey Yes, let's Do this It only takes 5 min

One of the things that always made me shudder in PHP was the lack of being able to implement generic class mixins in an easy way. The ability to avoid writing code multiple times is important to me as a developer, as it makes me more efficient at my job, so I can do more important code in the same amount of time, or slack off more while maintaining the same code output (this mainly depends on my mood at any one time).

If I had a dollar for every time I had to write a set of functions that I knew I’d written before, but also knew there was no way of avoiding, I’d have… well… not really that much, but at least enough to cover a night out. Bear with me on this one, there’s a fair bit of PHP code. (For the record I’d usually hunt down the functions and copy paste them.)

Here is a View class with a basic set of functions which allow me to implement something akin to the mixin design pattern.

class HtmlView {
 	protected $_helpers = array();
	public function addHelper($obj)
  	{
 		array_push($this->_helpers, $obj);
		return $this;
	}

	public function __call($name, $params)
	{
		foreach($this->_helpers as $helper)
		{
			if(is_callable(array($helper, $name )))
				return call_user_func_array(array($helper, $name), $params);
		}

		throw new Exception('Attempted to call nonexistent method ' . $name . ' on ' . __CLASS__);
	}
}

I could now create a helper class with a bunch of methods that I want to be able to access from my HtmlView.

class TagViewHelper{
	public function linkFor($url, $name)
	{
		return sprintf('<a href="%s">%s', $url, $name);
	}
	# the rest of my bunch of methods here...
}

I could either add the TagViewHelper to my HtmlView class at instantiation, or pop it into the constructor.

public function __construct()
{
 	$this->addHelper(new TagViewHelper);
	# Add other view helpers here
}

Now I’m able to call the methods in the helper class from an instantiated HtmlView object.

<!-- somewhere deep inside code being called by our HtmlView object--&gt;
Check out my awesome &lt;?PHP echo $this-&gt;linkFor('http://malstaxidermy.com', 'Stuffed Mongooses'); ?&gt;.
</code>

This would happily create a link for my stuffed mongooses website.

--ADVERTISEMENT--

And the crowd goes wild…

This is pretty common stuff, and while some of you might be staring at your screens, screaming “Why didn’t you just create an abstract GenericMixin class and then extend from that?” I’d like to start by saying “Woah, kind sir! I have a point!”

While there are many reasons this isn’t an ideal solution, I’m just going to pick on two.

  1. 90% of the time, I’m not in control of the objects I’m extending. The PHP framework we use consists of quite a few submodules which all work in whacky and wonderful (read: annoying) ways, which creates headaches when editing the root class. Alternatively this could be a library that we are using, and generally you want to avoid editing external dependencies if at all possible.
  2. What if I wanted to add in different functionality which was often used? Drop in a flyweight / object caching implementation? PHP doesn’t handle multiple inheritance, so at this point we’re back at point one – placing the code directly in our classes, or having some ridiculous base abstract class with as many pattern implementations as possible.

What’s your point? I’m here for the Ruby!

The good news is that, like a lot of languages, Ruby has built in support for mixins. It’s as easy as defining a module, then including it in our class definition. The include statement in Ruby is nothing like the include statement in PHP. Whereas in PHP this would include a file, what we’re doing in Ruby is pulling in all the methods from the module into the class.

Let’s recreate our HtmlView functionality in Ruby.

module TagViewHelper
	def tag_for(url, title)
		"<a href='%s'&gt;%s&lt;/a>" % [ url, title ]
	end
end

class HtmlView
	include TagViewHelper
end

Now I could call tag_for(“http://malstaxidermy.com”, “Solid Snakes”) from code inside an instance of my HtmlView. At no point did I have to worry about the handling of Mixins, because this is handled by Ruby.

You’ve got to admit, that’s a lot less code. Mixin modules are one of the great features of Ruby, and allow us to consolidate common behaviour into a set of shared objects.

You might be wondering what happens if you had several methods with the same name. Ruby handles this by simply overwriting all previous methods with the last one added.

Do you have any stories, or advice about mixins in PHP or Ruby?

Note: This is a very basic example designed to show how recreating some functionality that takes a fair amount of code in PHP can be handled very quickly and easily with Ruby.

More:
Login or Create Account to Comment
Login Create Account
Recommended
Sponsors
Get the most important and interesting stories in tech. Straight to your inbox, daily.Is it good?