Проверьте, существует ли свойство в магически заданных свойствах

Существует много вопросов о предмете, в частности, этот вопрос , но это мне не помогает.

Существует неоднозначность между property_exists и isset поэтому, прежде чем задавать свой вопрос, я хочу указать на это:

property_exists

property_exists проверяет, содержит ли объект свойство без оценки его значения, он смотрит только на его видимость .

Итак, в следующем примере:

 <?php class testA { private $a = null; } class testB extends testA { } $test = new testA(); echo var_dump(property_exists($test, 'a')); // true // parent's private property becomes invisible for its child $test = new testB(); echo var_dump(property_exists($test, 'a')); // false 

Исеть

isset проверяет, существует ли значение в свойстве, учитывая, что оно не установлено, если значение равно false и null .

 <?php $var = null; echo var_dump(isset($var)); // false $var = ''; echo var_dump(isset($var)); // true $var = false; echo var_dump(isset($var)); // true $var = 0; echo var_dump(isset($var)); // true $var = '0'; echo var_dump(isset($var)); // true 

isset и property_exists по магически добавленным свойствам

Свойство может существовать с null значением, поэтому я не могу использовать метод __isset magic, чтобы узнать, существует ли свойство или нет. Я также не могу использовать property_exists мере добавления свойств с помощью магических методов.

Вот пример, но это всего лишь образец, потому что в моем приложении свойства волшебным образом хранятся вне объекта .

 class test { private $data = array(); public function __get($key) { echo "get $key\n"; return array_key_exists($key, $data) ? $data[$key] : null; } public function __set($key, $value) { echo "set $key = $value\n"; $this->data[$key] = $value; } public function __isset($key) { echo sprintf("isset $key ( returns %b )", isset($this->data[$key])); return isset($this->data[$key]); } } $test = new test(); $test->x = 42; isset($test->x); // 1 $test->y = null; isset($test->y); // 0 property_exists($test, 'y'); // 0 

Вот мой вопрос :

Есть ли волшебный метод или интерфейс SPL для реализации property_exist с волшебными добавленными свойствами?

Я не верю, что есть способ изменить функциональность property_exists () с помощью магических методов; вот список доступных магических методов в PHP. Однако вы должны иметь возможность изменить isset (), чтобы использовать любую логику, которая вам нравится.

 class test { private $data = array(); public function __get($key) { echo "get $key\n"; return array_key_exists($key, $data) ? $data[$key] : null; } public function __set($key, $value) { echo "set $key = $value\n"; $this->data[$key] = $value; } public function __isset($key) { echo sprintf("isset $key ( returns %b )", array_key_exists($key, $this->data)); return array_key_exists($key, $this->data); } } $test = new test(); $test->x = 42; isset($test->x); // 1 $test->y = null; isset($test->y); // 1 

Это эффективно устраняет (раздражающую) проблему с isset и nulls, переопределяя ее функциональность с помощью магического метода. Вместо использования isset () внутри __isset () мы используем array_key_exists (который обрабатывает нули, как и следовало ожидать). Таким образом, __isset () возвращает ожидаемый результат, когда задано значение null.

Это имеет недостаток, а именно, что переопределенная функциональность не дает тех же результатов, что и функция isset () по умолчанию. Таким образом, если этот объект необходимо использовать прозрачно с другими объектами (возможно, stdClass), то isset () вернет true для нулевых значений в объектах этого класса и false для нулевых значений в обычных объектах.

В зависимости от ваших потребностей это может быть или не быть жизнеспособным решением. Если вышеуказанная проблема является помехой, другой вариант может заключаться в определении интерфейса с помощью свойства keyIsSet () и применении этого интерфейса ко всем объектам, которые будут проверяться. Затем используйте $ obj-> keyIsSet («ключ»), а не isset ($ obj -> $ key). Не так элегантно, но немного лучше.

Проблема заключается в реализации функций __set и __get , я их модифицировал и работает как для isset и для property_exists

 <?php class test { private $data = array(); public function __get($key) { echo "get $key\n"; return $$key; } public function __set($key, $value) { echo "set $key = $value\n"; $this->$key = $value; } public function __isset($key) { echo sprintf("isset $key ( returns %b )", isset($this->$key)); return isset($this->$key); } } $test = new test(); var_dump(property_exists($test, 'x')); var_dump(isset($test->x)); $test->x = 42; var_dump(property_exists($test, 'x')); var_dump(isset($test->x)); ?>