4

I am storing some strings in my database, and I want to be able to get model attributes using them.

Basically, I can call a users booking like this

$user->bookings->date

in my controller and it works, and i'm storing a string in my database like this

'user->bookings->date'

How can I use this string from the database to get the attribute? I'm hoping to be able to do something like

$user = User::findOrFail(1);
$string = 'user->bookings->date'; //This is fetched from the db normally
$booking_date = ${$string}; //Instead of writing $user->bookings->date

Is this possible?

1
  • Won't exactly work like that, as the object accessor -> needs to be outside of {} to work properly. i.e. something like ${$string1}->{$string2}->{$string3}; would work, but I'm not sure how to construct that dynamically. Commented Jun 18, 2019 at 16:15

2 Answers 2

2

I've found a solution that involves chaining object access from a static string:

$user = User::findOrFail(1);

$string = "user->bookings->date";
$params = explode("->", $string);

$var = null;
foreach($params AS $param){
    if($var){
        $var = $var->{$param};
    } else {
        $var = ${$param};
    }
}

dd($var);

On the first iteration of $params, set $var to the value of ${$param} ($user). Then, on the next iterations, set $var to the value of $var->{$param} ($user->bookings, $user->bookings->date). Then, finally, echo out (or dd()) the value of $var. In my test, this results in

"2019-06-18 12:06:00"

So while it requires a bit of additional logic, it is possible to set object access from a database string.

Sign up to request clarification or add additional context in comments.

3 Comments

This looks good, I've managed to find a method using the eval function, but every fibre of my being screams at me to not use it, just incase.
Yeah... eval() can be great when you know you will have absolute control of what's being evaluated, but performing it on something that can change a lot is a terrible idea :P
Yup, i'm not going to allow my users to type in a string, the string that is stored will be built dynamically, to avoid anyone simply typing $user->delete() or something.
0

You can use Arr::get helper method

With this, you can use "dot notation". So you should change the '->' with '.' and the 'user.' with ''

$string = "user->bookings->date";
$field = str_replace("->", ".", $string);
$field = str_replace("user.", "", $field);
// We want the string "bookings.date"

$user = User::findOrFail(1);

Arr::get($user, $field, "default value")

With this, you can go deeper as you need, and this returns you a single column or a collection if you have hasMany relation

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.