问题
How can I use __get() to return null in multilevel object property accessing the case like this below?
For instance, this is my classes,
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;
}
}
How I use it,
$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);
result,
null
but I get an error message with NULL when the input array is null
,
$type = null;
$type = $object->array_to_object($type,true);
var_dump($type->a->cc);
result,
Notice: Trying to get property of non-object in C:\wamp\www\test...p on line 68
NULL
Is it possible to return NULL in this kind of scenario?
回答1:
You can can return new property instead of null
public function __get($name)
{
return (isset($this->$name)) ? $this->$name : new property();
}
回答2:
Yes it is, but it's not so trivial to explain how. First understand why you run into that problem:
$value = $a->b->c;
This will first return NULL
for $a->b
. So actually you wrote:
$value = NULL->c;
So instead of NULL
on an unset item you need to return a NULL
-object (let's namne it NULLObect
) that works similar to your base class and that represents NULL
.
As you can imagine, you can not really simulate NULL
with it in PHP and PHP's language features are too limited to make this seamlessly.
However you can try to come close with the NULLObect
I've describben.
class property
{
public function __get($name)
{
isset($this->$name) || $this->$name = new NULLObject();
return $this->$name;
}
}
class NULLObject extends Property {};
Take care that this might not be exactly what you're looking for. If it does not matches your need, it's highjly likely that PHP is the wrong language you use for programming. Use some language that has better features of member overriding than PHP has.
Related Question:
- Working with __get() by reference
回答3:
Yes, I know it's been 4 years ago, but I had a similar problem this week, and while I trying to solve it, I found this thread. So, here is my solution:
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
来源:https://stackoverflow.com/questions/10462234/how-to-use-get-to-return-null-in-multilevel-object-property-accessing