Fun PHP #1

Особенности поведения

Сегодня говорим про PHP. Задачка первая. Дан код:

<?php
class HR {
public $foo = 1;
}

$Obj1 = New HR( Foo.bar() );
$Obj2 = new stdClass( someDo( $Obj1 ) );

#EOF#

Код дан как есть. Вопрос: что тут происходит и как отработает?

Ответы

Код отработает без ошибок, если версия интепретатора 5.6.0–5.6.30, 7.0.0–7.0.27, несмотря на то, что происходит обращение к несуществующему классу и вызов несуществующей функции.

Во всех остальных будет генерироваться ошибка:

Почему так происходит?

Вы можете сами догадаться, если я изменю код следующим образом:

<?php
class HR {
public $foo = 1;
function __construct(){}
}

$Obj1 = New HR( Foo.bar() );
$Obj2 = new stdClass( someDo( $Obj1 ) );

#EOF#

Выведет ошибку:

PHP Notice:  Use of undefined constant Foo - assumed 'Foo' in /experiments/1.php on line 24
PHP Fatal error: Uncaught Error: Call to undefined function bar() in /experiments/1.php:24
Stack trace:
#0 {main}
thrown in /experiments/1.php on line 24

Как так? Что происходит?

Все дело в парсере. Если у класса нет конструктора, то зачем парсить код, который передается как аргумент? Значит если нет конструктора, то можно писать любую ахинею и все что угодно и это не влияет на работу и скорость выполнения. Как вы понимаете у базового класса stdClass нет конструктора.

Скорее всего это был багофича, так что обновляйтесь и используйте только свежие версии интепретаторов (в которых могут быть новые баги =)).

Зачем знать такое?

Часто слышу в свой адрес что задачи все непрактичные, что этими задачами хрен что проверишь и вообще… Так вот, представьте ситуацию: у вас проект с n-летней историей. У вас сотни тысяч строк кода. Вы делаете рефакторинг и переписываете какой-то API, в результате которого что-то где-то поменялось кардинально. И у вас может сложиться ситуация, когда вы не заметите такие вот “мертвые” куски, причем вы будете думать что они рабочие при отладке. Крышу сносит, когда ты что-то меняешь — а ничего не происходит. А еще сильнее сносит крышу, когда ты видишь что тут вызов функции есть, а функции нигде такой уже давно нет.

Собственно эту задачу я придумал по мотивам реальной истории из своей практики.

И да, обновитесь до последней версии PHP и все будет ок.

UPD

В продолжении темы, похожая по духу и поведению задачка: