Class Method Chaining in PHP

When you call a class method in PHP, quite often, you expect to get back a value. This value may be a boolean, a string, an array, an Exception object, whatever. Perhaps you use this return to determine whether an error happened, or maybe to store a cleaned value in the database. A neat technique is to return a reference to the object whose method you just called, so that you can reuse the same object without having to explicitly call it again. This is called chaining.

To chain a class method, you simply have to return the $this variable rather than your ordinary return value. By doing so, you can immediately use the return from your method call to invoke another call. Take the following code for example (assume the class used exists somewhere):

toggle plain-text
  1. <?php
  2.  
  3. $class = new MyUserClass;
  4.  
  5. $class->authenticate('username', 'p4ssw0rd');
  6. $class->log_attempt();
  7. $class->redirect();

In the above sample, we've instantiated a class for handling various user tasks, and have made a few calls. What sticks out about this code snippet, is that we've made several calls to methods of the same object, and we haven't used a single return value for anything. This class is begging to be chained! To chain these calls, the class methods would have to look something like:

toggle plain-text
  1. public function authenticate($username, $password)
  2. {
  3.     logic here...
  4.     ... .. .
  5.    
  6.     return $this;
  7. }
  8.  
  9. public function log_attempt()
  10. {
  11.     logic here...
  12.     ... .. .
  13.    
  14.     return $this;
  15. }

With this structure, we can now chain our method calls together like so:

toggle plain-text
  1. $class->authenticate('username', 'p4ssw0rd')->log_attempt()->redirect();

Since the authenticate method returns a reference to its class, which happens to also be stored by reference in the $class variable, calling $class->authenticate('username', 'p4ssw0rd')->log_attempt() is the same as calling $class->log_attempt() above. Since log_attempt returns a reference to its class as well, you can continue to chain more method calls. The process only stops once you have reached a method that does not return a reference to itself. If you reach a method that returns something else and you attempt to chain another method call, you may encounter an error or get something you didn't expect back.

One of the best chained method implementations I've seen to date is the Kohana Framework's Database Query Builder class. Consider the following method chain:

toggle plain-text
  1. $result = $this->db->from('users')->select('username')->where('id',1)->get();

This method chain set demonstrates the Query Builder's power to, well, build queries! Each method call builds the query for its namesake's SQL counterpart. The sample above would generate the following query.

toggle plain-text
  1. SELECT username FROM users WHERE id = 1;

The final call, get(), executes the query and returns the result. Pretty snazzy eh? The best part about the Query Builder class, is that the sequence can be called in most any order, within reason. Since each of the methods returns a $this, the above sample could be reworked to the following:

toggle plain-text
  1. $result = $this->db->select('username')->from('users')->where('id',1)->get();

Since PHP is pretty forgiving when it comes to whitespace, you can make your code a bit easier to read by adding some newlines to your chains. Consider the user code from earlier in this tutorial:

toggle plain-text
  1. $class
  2. ->authenticate('username', 'p4ssw0rd')
  3. ->log_attempt()
  4. ->redirect();
  5.  

Method chains are a nice way to simplify the use of multiple methods for all types of classes, especially for classes like the Query Builder above. The downside is that you lose your return values, so this technique may not be appropriate for all classes and situations. Experiment with them some more, and when you feel confident, check out the Chainable Interface Tutorial.

};