Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

cariboufute's avatar

withDefault doesn't work with relation()->first()

I find it weird that when using withDefault() on a belongsTo relationship, I will receive the default model only when using a dynamic property. For example...

class User {
    //...

    public function role(): BelongsTo
    {
        return $this->belongsTo(Role::class)->withDefault(['name' => 'admin']);
    }
}

$user = new User(); // having no role
$methodRole = $user->role()->first()->name; // ErrorException: Attempt to read property "name" on null
$propertyRole = $user->role->name // 'admin'

Is this supposed to be this way? Isn't this a bug?

0 likes
4 replies
mabdullahsari's avatar

No, that's supposed to work that way. You are explicitly querying for a role in the second snippet, which completely bypasses your default definition.

tykus's avatar

I wouldn't say it is a bug; you are getting a separate result whenever using the (relationship) Builder. The result of $user->role()->first() is null.

cariboufute's avatar

Interesting! I thought calling the dynamic attribute was only syntactic sugar for relation()->first() or relation()->get() but there is more involved. I will check the Laravel code for more explanation.

cariboufute's avatar
cariboufute
OP
Best Answer
Level 1

Now I get it. Writing $user->role is the equivalent of writing $user->role()->getResults(), not $user->role()->first().

The getResults for BelongsTo class is this:

public function getResults()
{
    if (is_null($this->child->{$this->foreignKey})) {
        return $this->getDefaultFor($this->parent);
    }

    return $this->query->first() ?: $this->getDefaultFor($this->parent);
}

You don't have any getDefaultFor in BelongsToMany relationship, for instance.

So withDefault only works with dynamic properties. Maybe we should add a note on documentation to make it clear? https://laravel.com/docs/8.x/eloquent-relationships#default-models

Please or to participate in this conversation.