Как я могу использовать __get () для возврата null в свойство многоуровневого объекта, обращаясь к случаю, подобному приведенному ниже?
Например, это мои классы,
class property { public function __get($name) { return (isset($this->$name)) ? $this->$name : null; } } class objectify { public function array_to_object($array = array(), $property_overloading = false) { # if $array is not an array, let's make it array with one value of former $array. if (!is_array($array)) $array = array($array); # Use property overloading to handle inaccessible properties, if overloading is set to be true. # Else use std object. if($property_overloading === true) $object = new property(); else $object = new stdClass(); foreach($array as $key => $value) { $key = (string) $key ; $object->$key = is_array($value) ? self::array_to_object($value, $property_overloading) : $value; } return $object; } }
Как я его использую,
$object = new objectify(); $type = array( "category" => "admin", "person" => "unique", "a" => array( "aa" => "xx", "bb"=> "yy" ), "passcode" => false ); $type = $object->array_to_object($type,true); var_dump($type->a->cc);
результат,
null
но я получаю сообщение об ошибке с NULL, когда входной массив равен null
,
$type = null; $type = $object->array_to_object($type,true); var_dump($type->a->cc);
результат,
Notice: Trying to get property of non-object in C:\wamp\www\test...p on line 68 NULL
Можно ли вернуть NULL в этот сценарий?
Вы можете вернуть новое свойство вместо null
public function __get($name) { return (isset($this->$name)) ? $this->$name : new property(); }
Да, но это не так просто, чтобы объяснить, как это сделать. Сначала поймите, почему вы столкнулись с этой проблемой:
$value = $a->b->c;
Сначала будет возвращен NULL
для $a->b
. Итак, вы написали:
$value = NULL->c;
Поэтому вместо NULL
на неустановленном элементе вам нужно вернуть NULL
объект (давайте на нем NULLObect
), который будет похож на ваш базовый класс и представляет NULL
.
Как вы можете себе представить, вы не можете имитировать NULL
с ним в PHP, а языковые возможности PHP слишком ограничены, чтобы сделать это без проблем.
Однако вы можете попытаться приблизиться к NULLObect
который я описал.
class property { public function __get($name) { isset($this->$name) || $this->$name = new NULLObject(); return $this->$name; } } class NULLObject extends Property {};
Позаботьтесь о том, чтобы это не совсем то, что вы ищете. Если это не соответствует вашим потребностям, очень вероятно, что PHP – это неправильный язык, который вы используете для программирования. Используйте некоторый язык, который имеет лучшие функции переопределения членов, чем PHP.
Связанный вопрос:
Да, я знаю, что это было 4 года назад, но на этой неделе у меня была аналогичная проблема, и, пытаясь ее решить, я нашел эту тему. Итак, вот мое решение:
class NoneWrapper { private $data; public function __construct($object) { $this->data = $object; } public function __get(string $name) { return property_exists($this->data, $name) ? new NoneWrapper($this->data->$name) : new None; } public function __call($name, $arguments) { if (is_object($this->data)) { return (property_exists($this->data, $name)) ? $this->data->$name : null; } else { return null; } } public function __invoke() { return $this->data; } } class None { public function __get(string $name) { return new None; } public function __call($name, $arguments) { return null; } public function __invoke() { return null; } } $object = new NoneWrapper( json_decode( json_encode([ 'foo' => [ 'bar' => [ 'first' => 1, 'second' => 2, 'third' => 3, 'fourth' => 4, ], ] ]) ) ); var_dump($object->foo->bar->baz()); // null var_dump($object->foo->bar->third()); // 3