在PHP中允许链式调用方法吗?

6
例如,我有以下内容:
class A{
  __invoke(){
    // return an instance of class A itself
  }
}

我可以执行以下操作吗?
new A()()()()... or (new A())()()()...

这里的解释是什么?

假设PHP版本比5.4更新。

好的,我可以多解释一下为什么我要问: 我在使用ganon.php,它是一个开源HTML DOM解析器。 它使用类似于 $html_node('child_tag') 的语法返回另一个子节点$html_node,其中$html_node是HTML_NODE类的对象实例。所以我想知道是否可以在嵌套的HTML DOM结构中使用链接来进行选择。


我最讨厌的事情之一:有关语言语法的问题,其中包含无效代码片段... ;-P - Álvaro González
1
你要么能做到,要么不能,为什么不试试呢?话说回来,考虑使用流畅接口或应用建造者模式。这两种方法有点冗长,但更加清晰易懂。 - Ulrich Eckhardt
只是好奇,你为什么想要这样做? - SOFe
你的编辑完全改变了问题的意思。如果一个函数或方法返回一个对象,当然你可以从该对象调用方法。为什么不能呢?这与__invoke()无关。 - Álvaro González
2个回答

4

对于 PHP 版本 7.0.0 - 7.0.4,您可以按以下方式使用它:

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

echo (new A())(2);

输出:

__invoke2

4
我认为你所描述的行为在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

(演示)

您可能对 可变函数 功能感到困惑。如果 foo() 返回一个字符串 'bar',那么 foo()() 等同于 bar()

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

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

$a = new A();
$a()('Jim');

Hello, Jim!

(演示)

只要您的函数返回更多有效函数名称的字符串,就可以将其链接在一起,但是__invoke和类都没有发挥任何重要作用:

function one() {
    return 'two';
}

function two() {
    return 'three';
}

function three() {
    return 'four';
}

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

$a = one()()()();

Done!

(演示)

注意:上面所有的代码片段都需要 PHP/7,但是只要使用适当的圆括号和中间变量,就可以使用早期版本来模拟它们。


根据 UlrichEckhardt 的评论更新: 我忽略了“返回类A实例本身”的评论。如果您确实这样做,则代码将有效:

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


1
你的初始尝试中,不应该返回null,而是应该返回$this;。否则,返回值为null,当然就无法调用null - Ulrich Eckhardt
据我理解(原始)问题,@UlrichEckhardt并不想要foo()->bar()而是foo()()。但我认为他实际上想要完全不同的东西,__invoke()在这里实际上是无关紧要的。 - Álvaro González
我不确定原来的问题是什么。但是,你的第一个 class A 并没有证明 $a(0)(1); 不起作用,因为 __invoke() 应该返回 $this(或其他可以调用的内容)。是否这正是 coolgod 想要的并不重要。顺便说一下:在尝试 PHP 5.4 时,$a(0)(1); 给了我“PHP Parse error: syntax error, unexpected '(' in php shell code”。 - Ulrich Eckhardt
@UlrichEckhardt - 你的评论让我开始怀疑自己是否一开始就理解了问题。我刚刚更新了我的答案。 - Álvaro González

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接