Chaining functions with different return values?
Is it possible for a method to return different values depending on the context (how the return value is used)? For example, can a method return $this
when it is then used with an arrow operator to call another method (i.e., chaining method calls), but returns a scalar when the return value is not used in this way?
Case 1:
$result = $test->doSomething1(); // returns 4
// $result returns 4
Case 2:
$result = $test->doSomething1()->doSomething2();
// doSomething1() returns $this
// doSomething2() returns 8
Is there a way to accomplish this behavior?
source to share
If I understand the question correctly, you want the ( doSomething1
) method to return a value based on what the rest of the call chain looks like. Unfortunately, there is absolutely nothing you can do.
Common programming paradigms shared by all "all" languages (like methods, operators, and such work in the context of grammar) dictate that the result of an expression $this->doSomething1()
must be worked out before the result of a possible call ->doSomething2()
on it can be considered. Statically typed and dynamically typed languages do this differently, but a common factor is that an expression $this->doSomething1()
should be considered regardless of what should or should not.
In a nutshell: $this->doSomething1()
must return a specific type of value in both cases. And there is no way in PHP to have a value type that can behave like a number in one context and like an object with methods to call in another.
source to share
It is not possible for a function to return different values depending on whether the other function is called on the return value or not. You can emulate this with toString () (where a conversion to string is applied, or another function that you call at the end of each chain to get a value instead of an object:
$test = new foo();
echo $test->doSomething1(); // Outputs 1
$test = new foo();
echo $test->doSomething1()->doSomething2(); // Outputs 3
$test = new foo();
$result = $test->doSomething1()->done(); // $result === 1
$test = new foo();
$result = $test->doSomething1()->doSomething2()->done(); // $result === 3
class foo {
private $val;
function __construct($val = 0){
$this->val = $val;
}
function doSomething1(){
$this->val += 1;
return $this;
}
function doSomething2(){
$this->val += 2;
return $this;
}
function done(){
return $this->val;
}
function __toString(){
return (string)$this->val;
}
}
source to share
This answer involves creating a stack of internal calls in the class, so you can keep track of where you are in the method chain. This can be used to return $this
or whatever, depending on the context.
source to share