kaju74's avatar

How to dynamically access an object property?

Hi,

I'm using a MySQL JSON-Column inside Laravel to store all my user settings. This variable is casted to an object inside my model ($casts = [...]). So I can access a value like this:

Auth::user()->settings->notifications->comments

I can read & write this without any problems while hardcoding this...but is there a PHP-way to access this property using a variable?

My variable looks like this: $n = 'settings->notifications->comments'

And I've tryed:

Auth::user()->$n

...as well as...

Auth::user()->{$n}

...but nothing works. Any idea here?

Thank you, Marc

0 likes
5 replies
ahmeddabak's avatar
Level 47

Hi, yes you can solve this using a recursive method call, so you can split your $n variable


$value = Auth::user();

$n = 'settings->notifications->comments'

foreach (explode('->',$n) as $property) {
    $value  = get_nested_property($property, $value);
}

function get_nested_property($property, $object) {
    return $object->{$property};
}

you should get exactly what you want, but you can improve the logic, as a start i would not use -> to separate the properties, maybe a dot.

and then you should look up the php array dot notation it is used in laravel to access the config, it should give a good idea how you need to build your app.

1 like
tykus's avatar

I don't like this at all; it ultimately does nothing for readability nevermind violating the Law of Demeter anyway.

1 like
kaju74's avatar

I‘ll try that out. Thank you. It‘s for a dynamic form builder i.e. dynamic checkboxes. I‘m using objects directly casted through Laravel from the database to be able to use the new optional helper instead of using multi-if conditions in the blade template as well as having consequent writing paradigm through the whole app.

Accessing JSON inside a where-clause also uses the -> instead of array-dot-notation.

Marc

kaju74's avatar

Okay, so this is maybe not the best way to solve my problem. But, is there a better way to make this kind of stuff dynamically? I've created a simple @checkbox blade directive declared in the AppServiceProdiver:

Blade::include ('includes.form.checkbox', 'checkbox');

This include file look like:

<div class="field">
    <div class="ui fluid basic label">
        <div class="ui checkbox">
            <input type="hidden" name="...">
                   {{ HTML::checked(optional($b)->$v) }} value=1>
            <label>{{ $l ?? '[MISSING LABEL]' }}</label>
        </div>
    </div>
</div>

In my form, this include is called like:

@checkbox(['b' => $user, 'l' => 'Antwort auf einen meiner Kommentare', 'v' => 'settings->notifications->comments', 'op' => true])

So I pass the name of the property of the binded class (i.e. $user) and wonna include the "checked" attribute, if the value is true.

Regards, Marc

Please or to participate in this conversation.