The belongsTo
, hasOne
, hasOneThrough
, and morphOne
relationships allow you to define a default model that will be returned if the given relationship is null
.
Let’s say we have a relationship in Post model:
public function author()
{
return $this->belongsTo('App\Author');
}
And then somewhere in Blade file we have this:
{{ $post->author->name }}
Now, what if some post doesn’t have author? Meaning posts.author_id is NULL. You will get an error “Trying to get property of non-object”, meaning that there’s no $post->author, which is correct.
How I handle it usually:
{{ $post->author->name or 'Anonymous' }}
Or you can perform a check for existence:
@if ($post->author)
{{ $post->author->name }}
@else
Anonymous
@endif
What if I told you there’s a better way?
Apparently, Eloquent relationships allow to define “default” models, in case the model wouldn’t return anything.
public function author()
{
return $this->belongsTo('App\Author')->withDefault();
}
In this example, the author() relation will return an empty App\Author model if no author is attached to the post.
Furthermore, we can assign default property values to that default model.
/**
* Get the author of the post.
*/
public function user()
{
return $this->belongsTo('App\Models\User')->withDefault([
'name' => 'Anonymous',
]);
}
/**
* Get the author of the post.
*/
public function user()
{
return $this->belongsTo('App\Models\User')->withDefault(function ($user, $post) {
$user->name = 'Anonymous';
});
}
By using this structure, you don’t need to check anything in Blade anymore – just have the same
{{ $post->author->name }}
Source: https://laravel.com/docs/8.x/eloquent-relationships#default-models