How to provide a default model object for relationships?

October 26, 2018

If you have a relationship (such as a belongsTo()) relationship, it might not always return a result.

This will then mean that every time you do something like this:

<?php
$post = Post::first();
$author = $post->author; // what if the relationship in author() returns nothing?
echo $author->name; // $author might have been null, so this will cause an error

There are three main options to handling this:

1) wrap everything in optional() (which will let you do anything to that variable and it will return null if there was nothing set).

2) Wrap everything in if ($author) { ... } to make sure $author isn't a null value

3) or set a default model. If nothing is found for a relationship then it will create an empty object (of the same type as the relationship defines - in the case below it will be \App\User).

<?php
/**
 * Get the author of the post.
 */
public function user()
{
    return $this->belongsTo('App\User')->withDefault();
}
// you can also define some defaults for the default!
/**
 * Get the author of the post.
 */
public function user()
{
    return $this->belongsTo('App\User')->withDefault([
        'name' => 'Guest Author',
    ]);
}
/**
 * Get the author of the post.
 */
public function user()
{
    return $this->belongsTo('App\User')->withDefault(function ($user) {
        $user->name = 'Guest Author';
    });
}