I'm using Laravel's polymorphic relationships with a morph map to relate different models to a single table. However, I'm encountering an issue where only the first model in the morph map works, while the rest are ignored.
Here's how I've set up my morph map:
public function model()
{
return $this->morphTo();
}
Relation::morphMap([
'coupon' => Product::class,
'offer' => Product::class,
]);
public function scopefilter($query)
{
return $query->where(function ($query) {
// Include sliders with active morph relationships
$query->whereHasMorph('model','*', function ($query, $type) {
if (in_array($type,[ Blog::class, Coupon::class, Offer::class])) {
$query->active();
}
})->orWhereNull('model_type'); // Or include sliders without any morph
});
}
The extended models Coupon, Offer, and all inherit from the Product model.
The issue I'm facing is that when I try to retrieve a slider's associated model using $slider->model, it only returns the instance if it's a Product, but not if it's a Coupon, Offer, . However, when I change the morph map order, only the first one in the map works, and others are ignored.
I've verified that the database schema is correct, and all models are properly autoloaded. What could be causing this issue, and how can I resolve it?
If you have subclasses for Coupon
and Offer
then use them in the morph map. Having them both point the Product
class will make Laravel instantiate a Product
object.
Change
Relation::morphMap([
'coupon' => Product::class,
'offer' => Product::class,
]);
to
Relation::morphMap([
'coupon' => Coupon::class,
'offer' => Offer::class,
]);
From a quick search I found this old but helpful post which says you need to override the getMorphClass
function in your classes inheriting from Product
. For example:
class Coupon extends Product
{
public function getMorphClass()
{
return 'coupon';
}
}