Почему PHP вызывает __set () после unset () объявленного типизированного свойства? - PullRequest
1 голос
/ 02 мая 2020

(Отредактировал этот вопрос, старая версия цитировала неверную версию RF C.)

RF C для типизированных свойств в PHP говорит, что " Если типизированное свойство unset(), оно возвращается в неинициализированное состояние. " Однако в PHP 7.4 (по крайней мере, до 7.4.5) он, кажется, ведет себя по-разному, когда класс реализует __set(), и, следовательно, он не совсем похож на (исходное) неинициализированное состояние. Функция magi c не вызывается, когда свойство неинициализировано впервые, но вызывается (неожиданно), когда свойство устанавливается снова после сброса. Пример кода .

<?php

class X {
    public int $y;
    public function __set($name, $value) {
        echo "__set($name, $value) called";
        $this->$name = $value;
    }
}

$x = new X();
$x->y = 42; // Prints nothing, as expected.
unset($x->y);
$x->y = 43; // Prints `__set(y, 43) called`.

Я что-то пропускаю? Это ошибка в том, как PHP в настоящее время реализует unset() для типизированных свойств? Или __set() даже вызываться, когда неинициализированное типизированное свойство устанавливается впервые?

Ответы [ 2 ]

0 голосов
/ 02 мая 2020

Почему?

Для ленивых шаблонов инициализации.

Если типизированное свойство unset (), то оно возвращается в неинициализированное состояние , Хотя мы хотели бы убрать поддержку отмены установки свойств, в настоящее время эта функция используется для отложенной инициализации с помощью Doctrine

Так что в PHP 8 они могут запретить сброс объявленных свойств после предоставления некоторый альтернативный механизм для ленивой инициализации.

0 голосов
/ 02 мая 2020

Magi c геттеры / сеттеры срабатывают только для несуществующих свойств. Цитата: https://www.php.net/manual/en/language.oop5.overloading.php#object .set -> __set() is run when writing data to inaccessible (protected or private) or non-existing properties..

Итак, в вашем примере сначала переменные publi c существуют. После сброса переменная publi c не существует / не инициализируется, и вместо нее появляются magi c getter / setter.

Я думаю, что это поведение по-прежнему неверно, поскольку свойство существует, но оно не инициализировано. Должен ли быть отчет об ошибке?

...