Weird Problem: Trying to get property ‘name’ of non-object in Laravel Blade

I have four tables: users, countries, regions and townships.

In User.php model,

public function country() {
    return $this->belongsTo(Country::class, 'country_id');
}

public function region() {
    return $this->belongsTo(Region::class, 'region_id');
}

public function township() {
    return $this->belongsTo(Township::class, 'township_id');
}

In Country.php, Region.php and Township.php models,

public function users() {
    return $this->hasMany(User::class);
}

In users.blade, I tried to print user’s location

{{ $user->township->name }}, {{ $user->region->name }}, {{ $user->country->name }}

and, I got Trying to get property 'name' of non-object exception.

When I just tried to print country, region and township like {{ $user->township->name }}, {{ $user->region->name }}, {{ $user->country->name }}, it printed as below –

{"id":1,"region_id":1,"name":"Hlaing"}, {"id":1,"country_id":1,"name":"Yangon"}, {"id":1,"name":"Myanmar"}

It gets this exception in remote server only, there is no problem in local machine.

I have three views for all users, approved users and pending users. I have users.blade.php, users_approved.blade.php and users_pending.blade.php. Those blades are similar with only title text difference. There is no problem in approved users view (remote server also).

In MainController.php, I have those functions –

function users(Request $request) {
    $users = User::all();

    return view('users', [ 'users' => $users ]);
}

function users_approved(Request $request) {
    $users = User::where('approval_status', 'APPROVED')->get();

    return view('users_approved', [ 'users' => $users ]);
}

function users_pending(Request $request) {
    $users = User::where('approval_status', 'PENDING')->get();

    return view('users_pending', [ 'users' => $users ]);
}

I have already tried – php artisan view:clear, php artisan cache:clear, php artisan config:clear.

Answer

If your problem occurs only on remote machine, maybe it’s because the data stored there is different. In particular, for some users for some reasons (legacy records, code errors, not using transactions… etc.) some of their relations might just not be set.

One workaround, suggested on Eloquent docpage itself, is supplying default values for those tied models, used when relationship is missing in DB. For example:

public function country() {
    return $this->belongsTo(Country::class, 'country_id')->withDefault([
      'name' => 'Country Not Set',
    ])
}

public function region() {
    return $this->belongsTo(Region::class, 'region_id')->withDefault([
      'name' => 'Region Not Set',
    ])
}

… etc. Another option is running a DB query to fetch all the users on remote maching with the following condition:

WHERE country_id IS NULL 
   OR region_id IS NULL 
   OR township_id IS NULL

Depending on what you need, you may either modify those records or disable them in one way or another.