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?

+3


source to share


3 answers


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.

+4


source


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;
    }

}

      



Codepad example

+3


source


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.

0


source







All Articles