Method Chaining with PHP

Method chaining is a fluent interface design pattern used to simplyify your code. If you've used frameworks like Zend or jQuery, you probably have some experience with chaining. Essentially your objects return themselves, allowing you to "chain" multiple actions together.

Before I dive into the DIY aspects, here's an example of some cluttered code we can simplify with chaining. Let's say we want to fetch some data using Zend_Db. Assume we have a company database and want to know how many hours our employees this month. We could use a SQL query like this:

SELECT E.LastName, E.FirstName, E.Department, SUM(H.HoursLogged) AS HoursThisMonth FROM	Employees AS E INNER JOIN Hours AS H ON H.EmpID = E.EmpID WHERE H.DateLogged >= '12/1/2009' ORDER BY LastName, FirstName

This is perfectly acceptable to use, but hard to read. Using Zend_Db_Select to build the query, we could write it like this:

$startDate = '12/1/2009';

$db = Zend_Db::factory( /*options*/ );
$select = $db->select();
$select->from(
	array('E' => 'Employees'),
	array('LastName, FirstName, Department')
);
$select->joinInnerUsing(
	array('H' => 'Hours'),
	'EmpID',
	array('HoursThisMonth' => 'SUM(HoursLogged)')
);
$select->where('H.DateLogged > ?', $startDate);
$select->order(array('LastName', 'FirstName'));

What Chaining Looks Like

That certainly looks better, but see how every line starts with "$select->"? We can eliminate that repetition and clean up the code through chaining. Since Zend_Db_Select already implements chaining, we can do this:

$startDate = '12/1/2009';

$db = Zend_Db::factory( /*options*/ );
$select = $db
	->select()
	->from(
		array('E' => 'Employees'),
		array('LastName, FirstName, Department')
	)
	->joinInnerUsing(
		array('H' => 'Hours'),
		'EmpID',
		array('HoursThisMonth' => 'SUM(HoursLogged)')
	)
	->where('H.DateLogged > ?', $startDate)
	->order(array('LastName', 'FirstName'))
;

The whole query is built with a single line of code! This sample is much easier to read and maintain.

When Do I Implement Chaining?

Method chaining is best implemented on functions/methods that modify their parent object. They usually set a variable or perform some action without returning a result. Here are some examples of good candidates for chaining:

$log->write("Something just happened.");
$log->write("And it happened again.");

$mail->to('myself@domain.com');
$mail->subject('Test');
$mail->body('Hello World!');
$mail->send();

$cache->clear();
$cache->add("somekey", "andavalue");

How To Implement It

Implementation is extremely simple - simply return the object instance once the method has completed:

function someMethod (params)
{
	/* do stuff */
	return $this;
}

That's all you need to do! Since some of the original methods didn't return a value, returning "$this" shouldn't affect your scripts at all. Now your code looks like this:

$log->write("Something just happened.")
    ->write("And it happened again.")
;

$mail->to('myself@domain.com')
     ->subject('Test')
     ->body('Hello World!')
     ->send()
;

$cache->clear()
      ->add("somekey", "andavalue")
;	

Not all your methods need to (or should) chain. For example, the "$mail->send()" function above should probably return false if the message wasn't sent:

if($mail->to('myself@domain.com')->subject('Test')->body('Hello World!')->send())
	echo "Message Sent!";
else
	echo "Oops, something went wrong!";

You certainly don't have to use chaining in everything you do, but I'm sure you'll find some good uses for it.

About the Author

Colin O'Dell first started programming on an old Apple II-e at the age of 7. Within four years, he mastered several BASIC variants and sold his first commercial application. After tinkering with different languages and technologies for a few...

 
blog rss banner
 

Categories

View All

Testimonials

"Dear Mike - I wanted to take a moment to thank you and the Unleashed Team for such a wonderful experience with our new partnership.  Your team has been incredibly dedicated to making our...

Kelly Bedsole
Metro Offices

“Unleashed Technologies is a pleasure to work with. We needed an unusual, non-cookie-cutter web site on a very tight schedule, and Unleashed Technologies delivered.

Paul Jakubik
PureDiscovery Corporation