Filter Polymorphic Relationships Cleanly in Laravel Using whereHasMorph()
In Laravel, polymorphic relationships are powerful for structures like:
- Comments
- Activities
- Notifications
Example:
A comment may belong to:
- Post
- Video
- Product
Example Relationship
public function commentable()
{
return $this->morphTo();
}
The Challenge
Filtering polymorphic types manually becomes messy.
Laravel provides a clean solution:
whereHasMorph()
Basic Usage
Comment::whereHasMorph(
'commentable',
[Post::class],
function ($query) {
$query->where('published', true);
}
)->get();
What This Does
- Finds comments belonging to posts
- Filters only published posts
Multiple Morph Types
Comment::whereHasMorph(
'commentable',
[Post::class, Video::class],
function ($query) {
$query->where('is_active', true);
}
)->get();
👉 Same condition applied across multiple morph models.
Real Project Example
Imagine activity logs:
Activity::whereHasMorph(
'subject',
[Order::class, Payment::class],
fn ($q) => $q->where('status', 'completed')
)->get();
Why This Is Useful
It helps you:
- Filter morph relations cleanly
- Avoid manual type checks
- Keep queries maintainable
- Handle multi-model systems elegantly
When to Use It
Use whereHasMorph() when:
- Working with
morphTo()relationships - Filtering multiple model types
- Building activity or comment systems