asergey's avatar

Bug in method whereMorphedTo

Method \Illuminate\Database\Eloquent\Concerns\QueriesRelationships::whereMorphedTo.

Update github.com/illuminate/database v11.19.0. github.com/illuminate/database/commit/a65ad7f719458a670787078b5cd396c8694cabce#diff-31571eec1a80d34561af81803e20f2754fba1763f161a5a4f04179632fe56ef9R484

Example from youtube.com/watch?v=M2vMjp44xLc

Expected result:

select * from `images` where `imageable_type` = 'App\Models\Category' and `imageable_id` = ?

Result after update:

select * from `images` where `categories`.`imageable_type` = 'App\Models\Category' and `categories`.`imageable_id` = ?

Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'categories.imageable_type' in 'where clause' (Connection: mysql, SQL: select * from images where categories.imageable_type = 'App\Models\Category' and categories.imageable_id = ?)

0 likes
1 reply
asergey's avatar

I managed to find the reason. The problem is calling the query builder only from the same model class via a static method.

I have class MaterialCard with item morph. I do the following:

$card = MaterialCard::firstWhere('item_type', 'handbook');
$card->copy();

Inside the copy method I call the builder for model MaterialCard. When called in this way, the \Illuminate\Database\Eloquent\Builder::$model variable retains the model with item_type=handbook, which results in an incorrect query being generated.

Example of incorrect result with static call:

public function copy() {
	MaterialCard::whereMorphedTo('item', Course::class)->dumpRawSql();
}

select * from `material_cards` where `handbook`.`item_type` = 'course' and `material_cards`.`archived_at` is null

Example of correct result with a call via the query method:

public function copy() {
    MaterialCard::query()->whereMorphedTo('item', Course::class)->dumpRawSql();
}

select * from `material_cards` where `material_cards`.`item_type` = 'course' and `material_cards`.`archived_at` is null

Thus, calling via the MaterialCard::query() method forces the creation of a new instance of the MaterialCard class inside the query builder, while calling MaterialCard::whereMorphedTo uses the previously loaded model with data.

Please or to participate in this conversation.