Jump to content
NotionCommotion

Setting deep object properties

Recommended Posts

I need to set a deep property if it is undefined or NULL such as shown below:

function setProperty($value, stdClass $config, $p1, $p2, $p3, $p4) {
    if(!isset($config->$p1->$p2->$p3->$p4) || is_null($config->$p1->$p2->$p3->$p4)) {
        $config->$p1->$p2->$p3->$p4=$value;
    }
}

$config=json_decode(json_encode(['a'=>['b'=>['c'=>['x'=>null, 'y'=>123]], 'x'=>123],'x'=>['x'=>123], 'x'=>123]));

setProperty(321, $config, 'a','b','c','x');
setProperty(321, $config, 'a','b','c','y');

But I wish the function to work regardless of property depth and came up with the following.  Recommendations for a cleaner way?  Maybe I should be working with arrays and array_merge_recursive()?

function setProperty($value, stdClass $config, array $properties) {
    $property=array_shift($properties);
    if(!count($properties)){
        if(!isset($config->$property) || is_null($config->$property)) {
            $config->$property=$value;
        }
    }
    else {
        if(empty($config->$property) || !is_object($config->$property)) {
            $config->$property=new \stdClass();
        }
        setProperty($value, $config->$property, $properties);
    }
}

$config=json_decode(json_encode(['a'=>['b'=>['c'=>['x'=>null, 'y'=>123]], 'x'=>123],'x'=>['x'=>123], 'x'=>123]));

setProperty(321, $config, ['a','b','c','x']);
setProperty(321, $config, ['a','b','c','y']);

 

Share this post


Link to post
Share on other sites

did you ever consider that having a structure so very deep is possibly a poor design?

Share this post


Link to post
Share on other sites
2 minutes ago, ginerjm said:

did you ever consider that having a structure so very deep is possibly a poor design?

Thanks ginerjm.  Good point, however, it is not my design (the objects are the json objects used to configure Highcharts) and realistically they will only be 3 or 4 deep max .   Any recommendations on the best approach?  Thanks

Share this post


Link to post
Share on other sites

Something cleaner?

isset($config->a->b->c->x) || $config->a->b->c->x = 321;
isset($config->a->b->c->y) || $config->a->b->c->y = 321;

Remember that isset() also covers the case where the value exists but is null.

It's cool to have something that can arbitrarily set properties, but make sure what you have to give up in return is worth it. Here, I don't think you're gaining nearly enough for the sacrifice in readability.

Share this post


Link to post
Share on other sites

It's not the detection which I have an issue with but how to set them.  Unlike arrays, I cannot just use $config->a->b->c->x=123 if a, b, or c is not set.

Ah yeah, I do remember (now) that isset() unlike array_key_exists() will return false upon null.  Thanks

Share this post


Link to post
Share on other sites

Oh, so the problem is that you don't know if ->a, ->b, or ->c are defined.

I would deal with the data as an array and not an object, and array_replace_recursive.

  • Like 1

Share this post


Link to post
Share on other sites
7 hours ago, requinix said:

I would deal with the data as an array and not an object, and array_replace_recursive.

I actually tried array_merge_recursive but found it did not meet my needs and ended up writing my own version.  Looks like doing so was not needed and array_replace_recursive is the right solutions.  Thanks!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.