Обновление PHP до 7.0.6 может «сломать» ваш код

сегодня в 10:39

Внимание! Будьте осторожны при обновлении PHP до версии 7.0.6! В этой версии был исправлено несколько важных багов, на которые мог неявно полагаться ваш код или код вашего фреймворка.

PHP bugs

Какие баги были исправлены?


bugs.php.net/bug.php? id=62059
bugs.php.net/bug.php? id=69659
bugs.php.net/bug.php? id=71359

Тестовый пример:


Самый лаконичный можно взять из описания последнего бага (www.pastebucket.com/97499 в оригинале)
class Test
{
    protected $attributes = [
        'attribute1' => 'value1',
    ];

    public function __get($name)
    {
        print "GET\n";
        if (array_key_exists($name, $this->attributes)) {
            return $this->attributes[$name];
        }

        trigger_error("Property $name does not exist");
        return null;
    }

    public function __isset($name)
    {
        print "ISSET\n";
        return array_key_exists($name, $this->attributes);
    }
}


$obj = new Test();

var_dump($obj->attribute1 ?? 'default');

//GET
//string(6) "value1"

var_dump($obj->attribute2 ?? 'default');

//GET
//PHP Notice:  Property attribute2 does not exist in /var/www/html/test.php on line 23
//string(7) "default"

А можно проще?


Да.

В определенных случаях при использовании конструкций языка isset () и empty () не использовался вызов магического метода __isset () при его наличии в классе, а вместо этого сразу вызывался __get () и решение принималось на основе того, что он вернет.

Теперь это исправлено. Можно надеяться, что во всех случаях применения isset () или empty () на «магические» свойства или «магические» ключи массива-объекта ArrayAccess будет сначала вызываться __isset ().

Чем это грозит лично мне?


Тем, что если в вашем классе есть метод __get (), но нет метода __isset (), ваш код «сломается». Отныне во всех таких случаях isset () будет всегда возвращать false, а empty () === true

Что делать?


Я предпочел бы откатиться до 7.0.5, а затем аккуратно отрефакторить код. Вряд ли у вас много мест, где есть __get (), но нет __isset (). Впоследствии было бы неплохо добавить в ваш анализатор кода соответствующее правило.

Пользователь

© Habrahabr.ru