Mastering Relationship Queries and Testing in Laravel v8.61.0
Overview
Laravel v8.61.0 introduces significant syntactic sugar to
Prerequisites
To follow this tutorial, you should have a solid grasp of
Key Libraries & Tools
- Laravel: The primary PHP web framework used for modern application development.
- Eloquent ORM: Laravel's built-in database mapper for interacting with tables as objects.
- Laravel Vapor: A serverless deployment platform forAWS Lambda.
- Laravel Forge: A tool for server management and application deployment.
Code Walkthrough
Simplified Relationship Querying
Previously, querying a relationship required a nested closure. The new whereRelation method flattens this syntax.
// Old way: Using closures
Office::whereHas('reservations', function ($query) use ($user) {
$query->where('user_id', $user->id);
})->get();
// New way: Clean and readable
Office::whereRelation('reservations', 'user_id', $user->id)->get();
Dynamic Polymorphic Queries
The whereMorphRelation method allows you to query polymorphic relations with optional type filtering or wildcards (*).
// Querying images belonging to any resource created before yesterday
Image::whereMorphRelation('resource', '*', 'created_at', '<', now()->subDay())->get();
Enforcing Morph Maps
To prevent the database from storing inconsistent fully qualified class names, use enforceMorphMap. This ensures every polymorphic model has a defined alias.
// Inside AppServiceProvider::boot
Relation::enforceMorphMap([
'office' => Office::class,
'user' => User::class,
]);
Syntax Notes
- Method Chaining: The
whereRelationmethod supports standard operator syntax (e.g.,'=', '<', '>') just like standardwhereclauses. - Wildcards: In
whereMorphRelation, the asterisk acts as a catch-all for all types defined in your morph map.
Practical Examples
Use createQuietly() in your test suites when you need to seed data without triggering side effects like automated emails or external API calls typically fired by model observers. Combine this with assertModelExists($model) to verify database state without manually refreshing the model instance.
Tips & Gotchas
Avoid the trap of inconsistent polymorphic types. If you implement a morph map halfway through a project's lifecycle without using enforceMorphMap, your database will contain a mix of short aliases and long class strings. This breaks queries that expect a single format.
