Существует много вопросов о предмете, в частности, этот вопрос , но это мне не помогает.
Существует неоднозначность между property_exists
и isset
поэтому, прежде чем задавать свой вопрос, я хочу указать на это:
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)); ?>