This is a design pattern called Fluent Interface. It's become popularized through some notable frameworks that use it, such as jQuery. It's a neat trick for writing compact, readable code (in some cases) but like many design patterns it is not suited to all situations.
The ->
symbol is actually just an operator. Similar to the way that +
or -
can be used to operate on numbers, the ->
operator can operate on objects and members. The PHP interpreter can simplify an expression like 5 + 4
down to just 9
, and it can simplify an expression like $a->b
as well. The expression $a->b
is evaluated by looking inside $a
for a member called b
.
Just like the +
operator can be used several times in an expression, e.g. 5 + 2 + 7
, the ->
operator can also be used several times. The PHP interpreter is left associative for the +
operator, which means it evaluates 5 + 2 + 7
as if it were written (5 + 2) + 7
, which evaluates to 7 + 7
, which in turn evaluates to 14
.
The ->
operator is also left associative. So an expression like $a->b->c
is interpreted in a similar fashion to the previous example: first the interpreter evaluates $a->b
by looking for a member called b
in a
, then it looks for a member called c
in that! This assumes that $a->b
actually evaluates to an object; if it doesn't, then the PHP interpreter will give you an error: "Trying to get property of non-object".
This paradigm can be extended indefinitely: $a->b->c->d->e->f->g->....
etc.
In the Fluent Interface design pattern, this is implemented by having all instance methods return the instance. So $a->b()
returns $a
. Therefore, $a->b()->c()
is exactly the same as calling $a->b()
and then calling $a->c()
.
Some people think the former is more readable than the latter. In some cases that's true but in other cases it's not. Like most design patterns, you need to use good judgement when deciding whether to use this pattern or not. Keep in mind this pattern can only work if the instance methods are called purely for their side effects. You can't return any other value from an instance method besides the instance itself, or else you will break the fluent interface.