2015-05-29 4 views
3

Почему этот код вызывает бесконечную рекурсию?Бесконечная рекурсия в выражении эха PHP

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

Figured так. Какой аккуратный способ вызвать бесконечную рекурсию. Спасибо за анализ, все тоже. – 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 Я уже в бесконечном цикле, я просто шучу.

Но да, это бесконечный цикл ..

Смежные вопросы