I am using PHP 5 and I've heard of a new featured in the object-oriented approach, called 'method chaining'. What is it exactly? How do I implement it?
-
1I'd say most if not all of those questions are about technicalities regarding chaining, this is more specifically about how to achieve it. – Kristoffer Sall-Storgaard Sep 16 '10 at 07:39
-
@Kristoffer the OP could easily have found how it is achieved from these questions. – Gordon Sep 16 '10 at 07:46
-
2@Kristoffer in addition, searching for [method chaining php on Google](http://www.google.de/q=method+chaining+php) would have given the OP a [tutorial](http://www.talkphp.com/advanced-php-programming/1163-php5-method-chaining.html) by [Salathe](http://stackoverflow.com/users/113938/salathe) as the very first result. I dont mind answering easy questions, but some people are just too lazy. – Gordon Sep 16 '10 at 08:00
-
6I submit for your perusal, [the definitive method chaining decision tree](http://chat.stackoverflow.com/transcript/message/4316194#4316194) – Aug 15 '12 at 06:30
10 Answers
It's rather simple, really. You have a series of mutator methods that all return the original (or other) object. That way, you can keep calling methods on the returned object.
<?php
class fakeString
{
private $str;
function __construct()
{
$this->str = "";
}
function addA()
{
$this->str .= "a";
return $this;
}
function addB()
{
$this->str .= "b";
return $this;
}
function getStr()
{
return $this->str;
}
}
$a = new fakeString();
echo $a->addA()->addB()->getStr();
This outputs "ab"

- 9,564
- 146
- 81
- 122

- 10,576
- 5
- 36
- 46
-
13
-
19@Nitesh that is incorrect. [Fluent Interfaces](http://www.martinfowler.com/bliki/FluentInterface.html) use [Method Chaining](http://martinfowler.com/dslwip/MethodChaining.html) as their primary mechanism, but [it's not the same](http://en.wikipedia.org/wiki/Fluent_interface). Method chaining simply returns the host object, while a Fluent Interface is aimed at creating a [DSL](http://en.wikipedia.org/wiki/Domain-specific_language). Ex: `$foo->setBar(1)->setBaz(2)` vs `$table->select()->from('foo')->where('bar = 1')->order('ASC)`. The latter spans multiple objects. – Gordon Sep 16 '10 at 07:32
-
4public function __toString() { return $this->str; } This will not require the last method "getStr()" if you're echoing out the chain already. – tfont Apr 22 '14 at 07:01
-
9@tfont True, but then we're introducing magic methods. One concept at a time should be sufficient. – Kristoffer Sall-Storgaard Apr 22 '14 at 08:49
-
4Since PHP 5.4 it's even possible to *everything* in one line: `$a = (new fakeString())->addA()->addB()->getStr();` – Philzen Jun 01 '15 at 18:49
Basically, you take an object:
$obj = new ObjectWithChainableMethods();
Call a method that effectively does a return $this;
at the end:
$obj->doSomething();
Since it returns the same object, or rather, a reference to the same object, you can continue calling methods of the same class off the return value, like so:
$obj->doSomething()->doSomethingElse();
That's it, really. Two important things:
As you note, it's PHP 5 only. It won't work properly in PHP 4 because it returns objects by value and that means you're calling methods on different copies of an object, which would break your code.
Again, you need to return the object in your chainable methods:
public function doSomething() { // Do stuff return $this; } public function doSomethingElse() { // Do more stuff return $this; }

- 700,868
- 160
- 1,392
- 1,356
-
-
@alex: I don't have PHP 4 to test with right now, but I'm pretty sure not. – BoltClock Sep 16 '10 at 06:23
-
4I didn't think so either, but it *should* work right? Perhaps if PHP4 wasn't so PHP4-ish. – alex Sep 16 '10 at 06:26
Try this code:
<?php
class DBManager
{
private $selectables = array();
private $table;
private $whereClause;
private $limit;
public function select() {
$this->selectables = func_get_args();
return $this;
}
public function from($table) {
$this->table = $table;
return $this;
}
public function where($where) {
$this->whereClause = $where;
return $this;
}
public function limit($limit) {
$this->limit = $limit;
return $this;
}
public function result() {
$query[] = "SELECT";
// if the selectables array is empty, select all
if (empty($this->selectables)) {
$query[] = "*";
}
// else select according to selectables
else {
$query[] = join(', ', $this->selectables);
}
$query[] = "FROM";
$query[] = $this->table;
if (!empty($this->whereClause)) {
$query[] = "WHERE";
$query[] = $this->whereClause;
}
if (!empty($this->limit)) {
$query[] = "LIMIT";
$query[] = $this->limit;
}
return join(' ', $query);
}
}
// Now to use the class and see how METHOD CHAINING works
// let us instantiate the class DBManager
$testOne = new DBManager();
$testOne->select()->from('users');
echo $testOne->result();
// OR
echo $testOne->select()->from('users')->result();
// both displays: 'SELECT * FROM users'
$testTwo = new DBManager();
$testTwo->select()->from('posts')->where('id > 200')->limit(10);
echo $testTwo->result();
// this displays: 'SELECT * FROM posts WHERE id > 200 LIMIT 10'
$testThree = new DBManager();
$testThree->select(
'firstname',
'email',
'country',
'city'
)->from('users')->where('id = 2399');
echo $testThree->result();
// this will display:
// 'SELECT firstname, email, country, city FROM users WHERE id = 2399'
?>
-
2this is what i call a good explanation...chaining methods always gives me goosebumbs!! – MYNE Feb 12 '16 at 13:24
-
How I identify (inside the method) the first and last elements (calls) in the chain. Because sometimes this is now just a list of operations to be executed in order, but something that should be done after collecting all elements. Like executing an SQL query here - but beware, you could do multiple chained calls on one object! Firt and last in each. – Andris Apr 04 '18 at 22:45
Another Way for static method chaining :
class Maker
{
private static $result = null;
private static $delimiter = '.';
private static $data = [];
public static function words($words)
{
if( !empty($words) && count($words) )
{
foreach ($words as $w)
{
self::$data[] = $w;
}
}
return new static;
}
public static function concate($delimiter)
{
self::$delimiter = $delimiter;
foreach (self::$data as $d)
{
self::$result .= $d.$delimiter;
}
return new static;
}
public static function get()
{
return rtrim(self::$result, self::$delimiter);
}
}
Calling
echo Maker::words(['foo', 'bob', 'bar'])->concate('-')->get();
echo "<br />";
echo Maker::words(['foo', 'bob', 'bar'])->concate('>')->get();

- 1,943
- 14
- 20
Method chaining means that you can chain method calls:
$object->method1()->method2()->method3()
This means that method1() needs to return an object, and method2() is given the result of method1(). Method2() then passes the return value to method3().
Good article: http://www.talkphp.com/advanced-php-programming/1163-php5-method-chaining.html
-
5The explanation is a bit off. The return values are not passed around. The methods simply return the host object. – Gordon Sep 16 '10 at 08:19
-
@Gordon Well, the host object is not returned. Any object can be returned and chained. – alexn Sep 16 '10 at 14:38
-
2Then I would argue it's not method chaining as defined by Fowler, e.g. [Make modifier methods return the host object so that multiple modifiers can be invoked in a single expression.](http://martinfowler.com/dslwip/MethodChaining.html) - if you return other objects, it's more likely a Fluent Interface :) – Gordon Sep 16 '10 at 14:58
-
Wow, I realize that I'm commenting on an almost 8 year old post.. But your link that you have there, is redirecting to some other website. Just fyi. – willbeeler Oct 19 '17 at 18:41
-
here is the original [2005 post by Fowler](https://www.martinfowler.com/bliki/FluentInterface.html), mentioning both Fluent Interface and Method Chaining: – Matt Smith Feb 06 '22 at 13:59
There are 49 lines of code which allows you to chain methods over arrays like this:
$fruits = new Arr(array("lemon", "orange", "banana", "apple"));
$fruits->change_key_case(CASE_UPPER)->filter()->walk(function($value,$key) {
echo $key.': '.$value."\r\n";
});
See this article which shows you how to chain all the PHP's seventy array_ functions.
http://domexception.blogspot.fi/2013/08/php-magic-methods-and-arrayobject.html

- 7
- 4

- 75
- 1
- 1
-
5This isn't really an answer so much as a link to a webpage with a potential answer. – faintsignal Dec 14 '16 at 22:16
A fluent interface allows you to chain method calls, which results in less typed characters when applying multiple operations on the same object.
class Bill {
public $dinner = 20;
public $desserts = 5;
public $bill;
public function dinner( $person ) {
$this->bill += $this->dinner * $person;
return $this;
}
public function dessert( $person ) {
$this->bill += $this->desserts * $person;
return $this;
}
}
$bill = new Bill();
echo $bill->dinner( 2 )->dessert( 3 )->bill;
I think this is the most relevant answer.
<?php
class Calculator
{
protected $result = 0;
public function sum($num)
{
$this->result += $num;
return $this;
}
public function sub($num)
{
$this->result -= $num;
return $this;
}
public function result()
{
return $this->result;
}
}
$calculator = new Calculator;
echo $calculator->sum(10)->sub(5)->sum(3)->result(); // 8

- 859
- 9
- 20
Below is my model that is able to find by ID in the database. The with($data) method is my additional parameters for relationship so I return the $this which is the object itself. On my controller I am able to chain it.
class JobModel implements JobInterface{
protected $job;
public function __construct(Model $job){
$this->job = $job;
}
public function find($id){
return $this->job->find($id);
}
public function with($data=[]){
$this->job = $this->job->with($params);
return $this;
}
}
class JobController{
protected $job;
public function __construct(JobModel $job){
$this->job = $job;
}
public function index(){
// chaining must be in order
$this->job->with(['data'])->find(1);
}
}

- 71
- 1
- 2
If you mean method chaining like in JavaScript (or some people keep in mind jQuery), why not just take a library that brings that dev. experience in PHP? For example Extras - https://dsheiko.github.io/extras/ This one extends PHP types with JavaScript and Underscore methods and provides chaining:
You can chain a particular type:
<?php
use \Dsheiko\Extras\Arrays;
// Chain of calls
$res = Arrays::chain([1, 2, 3])
->map(function($num){ return $num + 1; })
->filter(function($num){ return $num > 1; })
->reduce(function($carry, $num){ return $carry + $num; }, 0)
->value();
or
<?php
use \Dsheiko\Extras\Strings;
$res = Strings::from( " 12345 " )
->replace("/1/", "5")
->replace("/2/", "5")
->trim()
->substr(1, 3)
->get();
echo $res; // "534"
Alternatively you can go polymorphic:
<?php
use \Dsheiko\Extras\Any;
$res = Any::chain(new \ArrayObject([1,2,3]))
->toArray() // value is [1,2,3]
->map(function($num){ return [ "num" => $num ]; })
// value is [[ "num" => 1, ..]]
->reduce(function($carry, $arr){
$carry .= $arr["num"];
return $carry;
}, "") // value is "123"
->replace("/2/", "") // value is "13"
->then(function($value){
if (empty($value)) {
throw new \Exception("Empty value");
}
return $value;
})
->value();
echo $res; // "13"

- 2,130
- 1
- 25
- 28
-
This doesn't really answer the question ("What is method chaining?"). Also the original question is 8 years old and has already got a number of better answers – GordonM Apr 12 '18 at 09:39