PHP Method Chaining

I’ve been reading up on method chaining in PHP recently and I’ve actually decided to make use of it on the billing system I’m currently working on. You’d be surprised how useful it can actually be in some cases, so I figured I’d share. First of all method chaining is not for all circumstances by any means but it can make doing some code a lot easier and it can also be easier to understand.

First of all what is method chaining when doing it with PHP? The easiest example I can think of is constructing a database query.

 
$db = new Database; 
$db->select("name,email")->from("customers")->where("name='joe'")->limit("0,5")->execute();

In this case it doesn’t make a whole lot of sense to be using it. You’re constructing a database query with a bunch of functions now but it’s the easiest to understand when you’re first learning about it. So now lets look at a better example here of when it is actually really useful. In this case I’m going to create a simple validation system using method chaining.

 
$validation = new Validation();
$myvar = $_POST['somepostvariable'];
if ($validation->value($myvar)->required()->isInt()->execute())
{
	print 'validated';
}
else
{
	print 'not validated';
}

A very simple example there of it’s power I tried to lay it out as simple as possible so extra declarations and such. Now here’s what it would look like if we were to build the same function not using chaining.

 
$validation = new Validation();
$myvar = $_POST['somepostvariable'];
if ($validation->required($myvar) && $validation->isInt($myvar))
{
	print 'validated';
}
else
{
	print 'not validated';
}

So how did I create this chain? Well I first need PHP5 and here’s the actual code of the Validation class

 
Class Validation
{
	public $value = '';
	public $error_count = 0;
 
	public function __construct()
	{
 
	}
 
	public function value($value)
	{
		$this->value = $value;
		return $this;
	} 
 
	public function required()
	{
		if (empty($this->value))
		{
			$this->error_count++;
		}
		return $this;
	}
 
	public function isInt()
	{
		if (!is_numeric($this->value) || intval($this->value) !=$this->value)
		{
			$this->error_count++;
		}
		return $this;
	}
 
	public function execute()
	{
 
		if ($this->error_count>0)
		{
			$this->error_count = 0;
			return false;
		}
		else
		{
			return true;
		}
	}
 
}

So now how does this work? Well in PHP5 you can return objects so using this ability we return the object on each method that we want to be part of the chain. How we handle variables in this instance is make use of class based variables using $this->var. So we just increase the error count and finally use a final function which tells us that our chain has ended which will do the checks for us. Of course this is a very basic example and I do not actually use this code, but I hope someone will find it useful when looking for a good method chaining example.

3 Responses to “PHP Method Chaining”

  1. Christopher Vogt Says:

    Hej Tony,

    method chaining is nice, indeed. But so is exception handling, which makes your example obsolete (which is a good thing I hope :)). The code could read:

    $validation = new Validation();
    $myvar = $_POST['somepostvariable'];
    try
    {
    $validation->required($myvar) && $validation->isInt($myvar);
    print ‘validated’;
    }
    catch ( Exception $e )
    {
    print ‘not validated’;
    }

    Your validation class code would go down to

    Class Validation
    {
    public $value = ”;

    public function __construct()
    {

    }

    public function value($value)
    {
    $this->value = $value;
    return $this;
    }

    public function required()
    {
    if (empty($this->value))
    {
    throw new Exception();
    }
    return $this;
    }

    public function isInt()
    {
    if (!is_numeric($value) || intval($value) !=$value)
    {
    throw new Exception();
    }
    return $this;
    }

    public function execute()
    {
    return true;
    }

    }

    Isn’t this just nicer :)? At beast you would introduce a ValidationException or even more fine-grained Exception subclasses to distinguish (which you cannot using your solution, by the way).

    Kind regards

    Christopher

  2. Tony Says:

    Well depends on what you’re doing and it’s almost like a short form more than anything. But in the exception case I may want to list all the errors opposed to just throwing an exception every time. In this case you may put the exception at the execute for example. But point taken it would be a good idea for it to use exceptions but like I had said originally just a case example of how to do the chaining in the simplest manner.

  3. PHP Fluency | Mullen Mills Says:

    [...] Tony Baird has a nicely thought out article [...]

Leave a Reply