Attach withDefault() to belongsTo, hasOne, and morphOne relationships to return a blank or pre-populated model instance when the relation is null.
When a relationship is optional (such as a Post having an optional Author, or an Order having an optional PromoCode), accessing attributes directly ($post->author->name) can throw an Attempt to read property on null error if the relation is unset.
Using withDefault() returns an empty model instance instead of null.
Basic Default Model
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Post extends Model
{
public function author(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id')->withDefault();
}
}
When $post->user_id is null, $post->author returns a blank User instance where properties evaluate to null instead of throwing an error:
// Returns null without throwing an exception
echo $post->author->name;
Providing Default Attribute Values
You can pass an array of fallback values or a closure to pre-populate default attributes:
public function author(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id')->withDefault([
'name' => 'Guest Author',
'email' => '[email protected]',
]);
}
Summary
- Protects views and services from
Attempt to read property on nullexceptions. - Keeps Blade views clean by removing repetitive
$post->author?->name ?? 'Guest'ternary operators. - Applicable to
belongsTo,hasOne,hasOneThrough, andmorphOnerelations.
Related Tips
View all tips →Scope Pivot Table Queries with Closures in wherePivot() in Laravel 13.26
Laravel 13.26 allows wherePivot() and orWherePivot() to accept closures, enabling direct reuse of local scopes defined on custom Pivot models.
Remove Global Eager Loading with withoutRelation()
Use withoutRelation() or unsetRelation() to remove eager loaded relationships on specific Eloquent queries or model instances.