Skip to content

PHPLARA-257 Replay query macros when eager loading MorphTo relations - #3559

Open
GromNaN wants to merge 1 commit into
mongodb:5.xfrom
GromNaN:phplara-257-morphto-eager-macros
Open

PHPLARA-257 Replay query macros when eager loading MorphTo relations#3559
GromNaN wants to merge 1 commit into
mongodb:5.xfrom
GromNaN:phplara-257-morphto-eager-macros

Conversation

@GromNaN

@GromNaN GromNaN commented Jul 29, 2026

Copy link
Copy Markdown
Member

PHPLARA-257

Eager loading a morphTo() relationship with withTrashed() returned null instead of the soft-deleted related model. Lazy loading was not affected.

class Photo extends Model
{
    public function hasImage(): MorphTo
    {
        return $this->morphTo()->withTrashed();
    }
}

Photo::with('hasImage')->get(); // hasImage was null when the related model is soft-deleted

MongoDB\Laravel\Relations\MorphTo::getResultsByType() was a stripped-down copy of the Laravel implementation, unchanged since 2015. It built the query with a plain $instance->newQuery(), which drops replayMacros(). That call is what makes withTrashed() work: MorphTo cannot apply it to the parent query because the macro only exists on the related model, so it buffers the call and replays it once per morph type. Without the replay the SoftDeletingScope is never removed.

The same omission silently disabled mergeConstraintsFrom(), with() and withCount(), which made morphWith(), morphWithCount() and constrain() no-ops on MongoDB.

The two reasons the override existed no longer apply:

  • DocumentModel::qualifyColumn() returns the column unchanged, so the parent's $instance->qualifyColumn($ownerKey) is already correct for MongoDB.
  • whereInMethod() is separately overridden to return whereIn instead of whereIntegerInRaw.

So the override is removed and the Laravel implementation is inherited. Tests cover withTrashed(), constrain() and morphWith(), all three failing on the previous code.

Fixes #3454
Fixes #1361

Copilot AI review requested due to automatic review settings July 29, 2026 12:04
@GromNaN
GromNaN requested a review from a team as a code owner July 29, 2026 12:04
@GromNaN
GromNaN requested a review from paulinevos July 29, 2026 12:04

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes eager loading of MorphTo relations when query macros (notably withTrashed()) must be replayed per morph type, aligning MongoDB behavior with upstream Laravel and restoring buffered macro/constraint behavior during eager loading.

Changes:

  • Removes the MongoDB-specific MorphTo::getResultsByType() override so the package inherits Laravel’s macro-replay implementation.
  • Adds a regression test covering lazy vs eager loading for morphTo()->withTrashed() against a soft-deleted related model.
  • Extends the test Photo model with a hasImageWithTrashed() relation for the new test.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
tests/RelationsTest.php Adds a regression test for eager-loaded morphTo()->withTrashed() returning soft-deleted related models.
tests/Models/Photo.php Adds a hasImageWithTrashed() morph-to relation used by the new test.
src/Relations/MorphTo.php Removes the custom getResultsByType() override to rely on Laravel’s implementation (enabling macro replay/constraint merging).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/RelationsTest.php Outdated
Comment thread src/Relations/MorphTo.php
getResultsByType() was a stripped-down copy of the Laravel
implementation, unchanged since 2015. Building the query with a plain
newQuery() dropped replayMacros(), which is the only way withTrashed(),
withoutTrashed(), onlyTrashed() and buffered select() calls reach the
related model query. It also dropped mergeConstraintsFrom(), with() and
withCount(), silently turning morphWith(), morphWithCount() and
constrain() into no-ops.

The two reasons for the override no longer apply: DocumentModel
::qualifyColumn() returns the column unchanged, so the parent's
$instance->qualifyColumn($ownerKey) is already correct, and
whereInMethod() is separately overridden to return whereIn.

Fixes mongodb#3454
Fixes mongodb#1361

Co-authored-by: Steve Porter <steve@steveporter.io>
@GromNaN
GromNaN force-pushed the phplara-257-morphto-eager-macros branch from fee8ae0 to 0513917 Compare July 29, 2026 12:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Eager loading MorphTo relationships with withTrashed() doesn't include soft-deleted models withTrashed in MorphTo relation

2 participants