Access global scope relationship?

Published 3 weeks ago by kevbrn

I am returning this

{
"id": 1,
"ProjectName": "XXX",
"contact_id": "2",
"created_by": "1",
"status": "1",
"created_at": null,
"updated_at": null,
"users": [
{
"id": 1,
"first_name": "XXXX",
"last_name": "XXXX",
"company_name": "XXXX",
"app_role_id": "1",
"project_id": "1",
"discipline_id": "17",
"project_role_id": "1",
"contact_id": "1",
"active_phases": "1",
"status": "1",
"verified": "0",
"email": "XXXX",
"cell_phone": "XXXXX",
"user_profile_pic": "nopic.png",
"created_at": "2017-10-28 16:48:24.000",
"updated_at": "2017-11-17 01:44:39.000",
"is_admin": "1",
"is_contact": "1",
"pivot": {
"project_id": "1",
"user_id": "1"
},
"user_discipline": [
{
"id": 17,
"name": "discipline_id",
"value": "01. General",
"created_at": null,
"updated_at": null
}
]
},

Project has a relationship to User and User has a relationship to userDiscipline.

The query from the controller

    public function users(Project $project)
    {

        $project->load('users');

        return $project;

//        return view('projects.users', compact('project'));

    }

userDiscipline is a global scope query on the User model

    protected static function boot()
    {

        parent::boot(); 

        static::addGlobalScope('userDiscipline', function ($builder) {
            $builder->with('userDiscipline');
        });

    }

how do I access user_discipline:value ? doing $var->user_discipline->value gives Trying to get property of non-object.

Is this the correct approach? 'User' has several relationships that I need to return anytime the 'User' model is queried.

Thanks!

Best Answer (As Selected By kevbrn)
Snapey

If user_discpline is any array (of relations), i.e. a one to many relationship then you could have multiple values.

Do you have the same issue with $user->userDiscipline->first()->value

bobbybouwmann

You need to access it through users. Since it's a one-to-many relation you get a collection back.

$project->load('users');

foreach ($users as $user) {
    // Access your data here
    $user->userDiscipline->someField;
}
kevbrn
kevbrn
3 weeks ago (21,020 XP)

Thanks @bobbybouwmann that still gives me the property of non-object error.

In my view I'm attempting to access it.

@foreach($project->users as $user)

                                <tr>
                                    <td>{{ $user->first_name }}</td>
                                    <td>{{ $user->last_name }}</td>
                                    <td>{{ $user->company_name }}</td>
                                    <td>{{ $user->userDiscipline->value }}</td>
                                    <td>{{ $user->email }}</td>
                                    <td>{{ $user->cell_phone }}
                                    </td>
                                </tr>
@endforeach 

if I output just $user->userDiscipline I get

[{"id":22,"name":"discipline_id","value":"06. Structural","created_at":null,"updated_at":null}]

Just need to access "value"

Snapey
Snapey
3 weeks ago (708,325 XP)

whenever you loop over a set of data you have to beware of one or more of those relationships being missing.

This can be confusing because if you stick a dd into the loop it will stop on the first record and that one can appear ok.

to code defensively make sure there is a fallback in case of missing relations. For instance;

<td>{{ $user->userDiscipline->value ?? '' }}</td>

here the php7 null coalesce operator is used (??) and will use the second value if the first is null.

bobbybouwmann

@Snapey is right. Every relation can be empty, so you need to make sure you check on that or you give it a default value. Using either the PHP 7 way or the PHP5.6 way

// PHP7
<td>{{ $user->userDiscipline->value ?? '' }}</td>

// PHP5.6 
<td>{{ $user->userDiscipline ? $user->userDiscipline->value : '' }}</td>
Snapey
Snapey
3 weeks ago (708,325 XP)

actually in all versions of php, you can also use Blade's or operator

<td>{{ $user->userDiscipline->value or '' }}</td>

Look out for any output that has double arrows since user->userDiscipline will safely return NULL if it is not set but accessing a property of user->userDiscipline will throw an error

kevbrn
kevbrn
3 weeks ago (21,020 XP)

Thanks for the info guys. I implemented the check as suggested but its evaluating to NULL on every record, when in fact every record has data for the specified relationship. Its basically masking the "trying to get property of non-object error"?

@foreach($project->users as $user)
                                <tr>
                                    <td>{{ $user->first_name }}</td>
                                    <td>{{ $user->last_name }}</td>
                                    <td>{{ $user->company_name }}</td>
                                    <td>{{ $user->userDiscipline->value or '' }}</td>
                                    <td>{{ $user->email }}</td>
                                    <td>{{ $user->cell_phone }}
                                    </td>
                                </tr>
                            @endforeach 
Snapey
Snapey
3 weeks ago (708,325 XP)

what about user->user_discipline->value

kevbrn
kevbrn
3 weeks ago (21,020 XP)

@Snapey ya that too

kevbrn
kevbrn
3 weeks ago (21,020 XP)

I noticed that user_discipline is an array and not a collection? Is that right?

{  
   "id":210,
   "first_name":"Adam",
   "last_name":"XXXXX",
   "company_name":"XXXX",
   "app_role_id":"1",
   "project_id":null,
   "discipline_id":"22",
   "project_role_id":"76",
   "contact_id":null,
   "active_phases":null,
   "status":"1",
   "verified":"0",
   "email":"XXXXX",
   "cell_phone":"XXXX",
   "user_profile_pic":"nopic.png",
   "created_at":"2017-11-11 22:08:53.000",
   "updated_at":"2017-11-11 22:08:53.000",
   "is_admin":"0",
   "is_contact":"0",
   "pivot":{  
      "project_id":"1",
      "user_id":"210"
   },
   "user_discipline":[  
      {  
         "id":22,
         "name":"discipline_id",
         "value":"06. Structural",
         "created_at":null,
         "updated_at":null
      }
   ]
}

bobbybouwmann

It's an array because you output it as JSON. If you dd($data) you data you will see a collection there.

kevbrn
kevbrn
3 weeks ago (21,020 XP)

Thanks @bobbybouwmann

Cant seem to get this to do what I need it to. Will have to come up with another approach.

Snapey
Snapey
3 weeks ago (708,325 XP)

If user_discpline is any array (of relations), i.e. a one to many relationship then you could have multiple values.

Do you have the same issue with $user->userDiscipline->first()->value

kevbrn
kevbrn
3 weeks ago (21,020 XP)

@snapey That works! So it is 'OK' to have that in my view or is there a more blade friendly approach?

Thank you so much!

Snapey
Snapey
3 weeks ago (708,325 XP)

Yes, its ok, but the point is, if its a one to many, and we just pick the first value, what about the other values?

Please sign in or create an account to participate in this conversation.