How to use __get() to return null in multilevel ob

2019-02-25 08:28发布

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?

3条回答
混吃等死
2楼-- · 2019-02-25 08:37

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
查看更多
干净又极端
3楼-- · 2019-02-25 08:46

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:

查看更多
ら.Afraid
4楼-- · 2019-02-25 08:55

You can can return new property instead of null

 public function __get($name)
    {
        return (isset($this->$name)) ? $this->$name : new property();
    }
查看更多
登录 后发表回答