Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it allowed to chain invoke method in PHP? [closed]

for example, I have following:

class A{
  __invoke(){
    // return an instance of class A itself
  }
}

so can I do the following?

new A()()()()... or (new A())()()()...

and what is the explanation here? suppose PHP version is newer than 5.4

Ok, I may give a little more explanation why I ask: I was using ganon.php which is an open source html dom parser. It is using syntax like $html_node('child_tag') to return another child $html_node where $html_node is an object instance of class HTML_NODE. So I was thinking if I could use chaining to do the selection in a nested html dom structure.

like image 639
coolgod Avatar asked Mar 23 '16 09:03

coolgod


2 Answers

I don't think that the behaviour you describe actually works, even in PHP/7:

class A{
    public function __invoke($arg){
        echo __METHOD__ . "($arg) called" . PHP_EOL;
    }
}

$a = new A();
$a(0);
$a(1)(2)(3);
A::__invoke(0) called
A::__invoke(1) called
Fatal error: Function name must be a string

(demo)

You're probably confused by the variable functions feature. If foo() returns a 'bar' string, then foo()() equals bar():

class A{
    public function __invoke(){
        return 'hello';
    }
}

function hello($name) {
    echo "Hello, $name!" . PHP_EOL;
}

$a = new A();
$a()('Jim');
Hello, Jim!

(demo)

You can chain that as long as your functions return more strings with valid function names, but neither __invoke nor classes play any relevant role:

function one() {
    return 'two';
}

function two() {
    return 'three';
}

function three() {
    return 'four';
}

function four() {
    echo 'Done!';
}

$a = one()()()();
Done!

(demo)

Note: all code snippets above require PHP/7 but they could be emulated with earlier versions just using the appropriate parenthesis and intermediate variables.


Update based on UlrichEckhardt's comment: I overlooked the return an instance of class A itself comment. If you actually do so, code does work:

class A{
    public function __invoke($arg){
        echo __METHOD__ . "($arg) called" . PHP_EOL;
        return $this;
    }
}

$a = new A();
$a(0);
$a(1)(2)(3);

class A{
    public function __invoke($arg){
        echo __METHOD__ . "($arg) called" . PHP_EOL;
        return $this;
    }
}

$a = new A();
$a(0);
$a(1)(2)(3);

(demo)

Of course, this is PHP/7 syntax. For older versions, you need auxiliary variables that break the magic:

$a = new A();
$b = $a(1);
$c = $b(2);
$d = $c(3);
$d(4);
like image 167
Álvaro González Avatar answered Sep 28 '22 02:09

Álvaro González


For PHP versions 7.0.0 - 7.0.4 you can use it like as

class A{
  public function __invoke($x){
    return __FUNCTION__."$x";
  }
}

echo (new A())(2);

Output:

__invoke2
like image 28
Narendrasingh Sisodia Avatar answered Sep 28 '22 01:09

Narendrasingh Sisodia