Mastering Laravel 12.21: Global Factory Controls and Attribute Singletons
Overview
Prerequisites
To follow this tutorial, you should have a solid grasp of:
- PHP 8.2+: Specifically understanding attributes and classes.
- Eloquent ORM: Familiarity with factories and model relationships.
- Service Container: Basic knowledge of singletons and dependency injection.
Key Libraries & Tools
- Laravel Framework 12.21: The core PHP framework receiving these updates.
- Eloquent Factories: Tools for generating fake data for testing.
- PHP Attributes: Native metadata used for container configuration.
Code Walkthrough
Disabling Factory Relationships
When testing, you often want to create a model without triggering the creation of its parent relationships. Previously, you had to chain withoutParents() on every call. Now, you can disable them globally for a factory.
// In a test or service provider
PostFactory::don'tExpandRelationshipsByDefault();
// This now returns a model with user_id as null without creating a User
$post = Post::factory()->make();
querying Ranges Between Columns
Instead of manual where clauses to check if a single value (like a timestamp) falls between two different columns (like start_date and end_date), use the expressive whereValueBetween method.
$now = now();
$currentEvents = Event::whereValueBetween($now, ['start_date', 'end_date'])->get();
Class-Level Singletons
You can now skip the AppServiceProvider binding for singletons by using
namespace App\Services;
use Illuminate\Container\Attributes\Singleton;
#[Singleton]
class Counter
{
public int $count = 0;
}
Syntax Notes
- don'tExpandRelationshipsByDefault(): This static method acts as a global toggle for the factory's internal expansion logic.
- #[Singleton]: This attribute instructs the Laravelcontainer to resolve the same instance every time the class is requested, centralizing configuration within the class itself.
Practical Examples
- Performance Tuning: Use
don'tExpandRelationshipsByDefaultin large test suites to prevent unnecessary database writes, significantly cutting down execution time. - Event Management: The
whereValueBetweenmethod is perfect for booking systems, scheduling apps, or any platform where you must validate a specific time against a duration defined by two columns.
Tips & Gotchas
- Database Constraints: Remember that disabling factory parents will cause
create()to fail if your database schema has aNOT NULLconstraint on the foreign key. - Global State: Be careful with global factory settings in tests; ensure they don't leak into other tests by resetting them or using them within specific test groups.
