Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Issue with automaticallyEagerLoadRelationships() and withDefault() – Related Model Created with Missing Foreign Keys #55744

Copy link
Copy link
Open
@veneliniliev

Description

@veneliniliev
Issue body actions

Laravel Version

12.14.1

PHP Version

8.4

Database Driver & Version

No response

Description

When using Model::automaticallyEagerLoadRelationships() in combination with a relationship that uses withDefault() (for example, a morphOne wallet relationship), accessing the relationship in an Eloquent event like created or saved leads to Laravel returning a default (unsaved) related model. If you try to save this model (for instance, to initialize some data), it may be persisted without proper foreign key values, resulting in an integrity constraint violation (e.g., is null). holder_id
This is unintuitive and can easily cause hard-to-trace bugs in codebases that rely on eager loading and relationship defaults.

Example

Business Model:

class Business extends Model
{
    public static function booted()
    {
        static::automaticallyEagerLoadRelationships();
    }

    public function wallet()
    {
        return $this->morphOne(Wallet::class, 'holder')
            ->withDefault([
                'balance' => 0,
            ]);
    }
}

Wallet Model:

class Wallet extends Model
{
    public function holder()
    {
        return $this->morphTo();
    }
}

In BusinessObserver:

public function created(Business $business)
{
    // Access wallet and try to save it
    $business->wallet->updateBalance();
    // ...other logic
}

Result:

If the business does not have a wallet yet, $business->wallet returns the default wallet (not saved, belonging to the business). If you try to call $business->wallet->save() (possibly via updateBalance()), Laravel attempts to insert it, but and are null, which causes: holder_id``holder_type

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'holder_id' cannot be null

Expected Behavior

Related models returned by withDefault() should not be saved automatically unless all their required foreign keys are present. Alternatively, using automatic eager loading should not trigger the creation of a default related model that is not ready to be persisted.

Note:
When Model::automaticallyEagerLoadRelationships() is not used, the relationship with withDefault() works as expected and no integrity constraint violations occur.

Steps To Reproduce

  1. Enable in your model. automaticallyEagerLoadRelationships
  2. Define a relationship with withDefault.
  3. Within a model event, access and attempt to use/save the related model.
  4. Observe the failure if the related model was not created before the event handler.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.