2015-05-29 55 views
3

为什么此代码会导致无限递归?PHP echo声明中的无限递归

class Foo { 
    public static function newFoo() { return new Foo(); } 
    public function __toString() { 
     return "{${Foo::newFoo()}}"; 
    } 
} 

echo new Foo(); // Infinite recursion 
new Foo();  // Finishes normally 

这是因为__toString()返回一个对象吗?但这是不可能的,因为根据文档

此方法必须返回一个字符串,否则会发出致命的E_RECOVERABLE_ERROR级错误。 (ref

或者它只是在__toString()方法中无限递归?

+0

该方法返回一个字符串,但它返回,因为你把它周围的双引号将被评估的字符串。所以函数签名被满足,它返回一个字符串。邪恶的部分发生之后,因为字符串正在'eval()'d。 – Mjh

回答

7
echo new Foo(); 

创建Foo并试图echo它,这样做它投影调用魔术方法__toString对象为字符串。

在该方法中,但是,您调用静态方法Foo::newFoo,它返回一个新的对象,这又是铸造为字符串__toString本身,所以被再次调用。

所以是的,这里是无限递归。

澄清:

public function __toString() { 
    return "{${Foo::newFoo()}}"; 
} 

因为你被无限调用它相当于

public function __toString() { 
    $foo = Foo::newFoo(); 
    return "$foo"; // this is a cast as string, which invokes __toString() again. 
} 
+0

问题是'__toString'必须返回一个字符串。在OP的情况下,它确实会返回一个字符串,但该字符串被双引号括起来,所以它也被评估,这是造成混淆的原因。但是,从我+1。 – Mjh

+0

@Mjh感谢您的意见,我试图编辑答案,使其更清晰。 –

+0

如此。多么可能导致无限递归的方式。感谢您的分析,每个人也一样。 – Drakes

1

..

您回应echo new Foo();

和你再次调用它与:

'return "{${Foo::newFoo()}}";' 

public static function newFoo() { return new Foo(); } 

这里有一个样本模拟:

echo new Foo(); 

会调用这个:

public function __toString() { 
    return "{${Foo::newFoo()}}"; 
} 

//你叫

public static function newFoo() { return new Foo(); } 

//并会再次执行

public function __toString() { 
    return "{${Foo::newFoo()}}"; 
} 

//并再次调用

public static function newFoo() { return new Foo(); } 

//并会一次又一次地执行

public function __toString() { 
    return "{${Foo::newFoo()}}"; 
} 

//并会一次次给

public static function newFoo() { return new Foo(); } 

Ooooohhh我已经陷入了无限循环,我只是在开玩笑。

但是,是的,这是一个无限循环..