PHP5 Setters Should Return $this
I think that as a convention, I will now have all setters return $this instead of null. I arrived at this decision from messing around with the Specification design pattern (“Domain Driven Design” by Eric Evans, pg. 224). When I was creating a chain of specifications in my Policy object, I ended up making a large number of Factory methods, one for each concrete Specification type. During one refactoring, I added an attribute with a setter for if this was a “normal” specification or just a “warning” specification (one that would log a normal error message if not satisfied, but still allow the policy to take place if other specifications on the chain were sufficient). A little more info on my experiment with the Specification pattern here.
Anyway, you end up with a factory method like this:
<?php
private function fieldEquals($field, $value, $msg, $logdesc) {
return new FieldEqualsSpecification($field, $value, $this->log, $msg, $logdesc);
}
?>
And if you want a small variation of this method that sets the warning, you can do:
<?php
private function fieldEqualsWarn($field, $value, $msg, $logdesc) {
$ret = $this->fieldEquals($field, $value, $msg, $logdesc);
$ret->setWarning();
return $ret;
}
?>
But, if you have the Specification::setWarning() method return $this instead of null (void) you can eliminate the temporary variable in the second Factory method and end up with this code:
<?php
private function fieldEqualsWarn($field, $value, $msg, $logdesc) {
return $this->fieldEquals($field, $value, $msg, $logdesc)->setWarning();
}
?>
Breaking it down the way the PHP parser does, you get:
$this->fieldEquals() returns an object
which we call the setWarning() method on
which returns an object that we return from this method
I’ll have to contemplate it a bit, but “When in doubt, return $this” may become a mantra for my PHP5 development 😉
I see the concept in this case, but could you explain further why you think it might be a good idea in general. For example, would it evolve into a standard error handling system? And how does it work with other patterns?
Well, to elaborate a bit, if you return nothing from a method, that it the end of the line (literally, there can be nothing but a ; after the method call ) and nothing is returned, so you must have a temporary variable to hold the instance.
Since the setter (in my case setWarning) returned $this, you can continue to chain further methods. You could have functions like:
function mySpecialFoo() {
return GeneralFooFactory()->setFoo(‘bar’)->setBlah(‘baz’);
}
It is all just conveniance more than anything.
I agree that it’s often convenient, but I think applying this approach as a rule is at best idiosyncratic and at worst really counter-intuitive.
I wouldn’t expect to be able to do this in code: $user->setName(“Joe”)->setEmail(“joe@example.com”);
Without making reference to any patterns or academic theory, I would suggest that the only time it is intuitive for setters to return $this is when the modified state of the object is salient for the calling code. Or, in other words, when the way that the setter method has changed the state of the object is important for further operations of the calling code. (Does that make any more sense?) The most “makes sense” place I’ve seen this is in stringing together Criterion objects to form a Criteria: $criterion->addAnd(someclause)->addOr(someclause). At each step in that example, the new state of the object is significant.
Of course concise code is often really attractive, but there are other forces at work in shaping the way people use these languages.
I agree it could be a bit counter-intuitive, perhaps a violation of the Principal of least suprise? However, the code arose from me actually writing the code expecting it to work, scratching my head for a bit as to why I was returning NULL, and then figuring out the workaround that allow the original chain to work.
The criterion example is interesting as well in that it is similar to my specification pattern. When chaining specification, I have a Specification::and_() method that also returns $this so I can end up with
$policy = $this->SpecType1()->and_(
$this->SpecType2()->and_(
$this->SpecType3()
));
Where $this->SpecType# are private factory methods.
JMock works this way as well when setting expectations.
Interesting, this reminds me of operator= in C++, where your return this in order to allow chaining …
e.g. bill gates = microsoft = evil;
Also, I’ve seen a some C++ apps do this with setters…
criteria = new Criteria()->
setLimit(30)->
setOffset(10)->
add(Column1, 10, equal)->
add(Column2, 60, equal)->
orderByAsc(Column3);
Personally I have no propblem with it, and in situations where you have long constructors with lots of optionals, it makes sense to break things down into setters and chain these after the constructor. This gets round the issue of parameter orders.
This is just called the fluent pattern… nothing new here folks, go back to your homes…