php-standard-library/default
Provides a DefaultInterface for PHP classes to expose standardized “default” instances. Helps ensure consistent default construction across libraries and apps with a simple, shared contract.
DefaultInterface aligns with Laravel’s dependency injection (DI) and service container patterns, enabling standardized default object creation. It complements Laravel’s existing mechanisms (e.g., App::bind(), Singleton bindings) by introducing a contract-driven approach, which is particularly useful for enforcing consistency in modular architectures (e.g., plugins, microservices).User or Order stubs for testing/mocking).return []).Cache::rememberForever() could use a default CacheItem).getDefault() method for test doubles.DefaultInterface is minimal (public function getDefault(): static), requiring only a single method implementation. This makes it retroactive-friendly for existing classes.App::bind('default-user', fn() => User::getDefault())).Macroable traits or custom traits for shared default logic.getDefault() initializes heavy objects (e.g., database connections), lazy-loading via Laravel’s container is critical.getDefault() instead of direct instantiation, increasing initial migration effort.getDefault() be eager (initialized on class load) or lazy (initialized on first call)?Macroable traits or AppServiceProvider bindings achieve the same goal with less overhead?AppServiceProvider or modular providers (e.g., AuthServiceProvider for default User instances).RepositoryInterface, ServiceInterface).Resource or Collection responses (e.g., DefaultApiResponse).createMock() with ClassName::getDefault() in PHPUnit/Pest tests.DefaultFormState).Subscription stubs for testing.Phase 1: Pilot Implementation (Low Risk)
DefaultConfig, EmptyCollection, DefaultUser).class User implements DefaultInterface {
public function getDefault(): static {
return new static([
'name' => 'Anonymous',
'email' => null,
'is_active' => false,
]);
}
}
Phase 2: Service Container Integration
AppServiceProvider:
public function register(): void {
$this->app->bind('default-user', fn() => User::getDefault());
$this->app->bind('default-config', fn() => Config::getDefault());
}
new User()) with container resolution:
$defaultUser = app('default-user'); // Instead of new User()
Phase 3: Enforce via Interfaces (Optional)
DefaultInterface to shared contracts (e.g., RepositoryInterface, ServiceInterface).interface RepositoryInterface {
public function getDefault(): static;
}
Phase 4: Testing Optimization
getDefault():
// Before:
$mockUser = $this->createMock(User::class);
// After:
$defaultUser = User::getDefault();
Model stubs (e.g., User::getDefault() for seeders or factories).| Step | Priority | Effort | Dependencies | Key Deliverable |
|---|---|---|---|---|
Add DefaultInterface to pilot classes |
High | Low | None | 2–3 classes with getDefault() implemented. |
Bind defaults in AppServiceProvider |
Medium | Medium | Pilot classes | Container-bound defaults. |
Update tests to use getDefault() |
Low | High | Pilot classes | Test suite compatibility. |
| Enforce via interfaces in shared contracts | Medium | Medium | Laravel’s DI system | DefaultInterface in RepositoryInterface. |
| Document patterns for team adoption | Low | Low | All prior steps | Internal wiki/example repo. |
Performance profile getDefault() calls |
Low | Medium | Pilot classes | Optimized lazy-loading strategy. |
User::getDefault() instead of manual object creation).DefaultInterface to every class may feel redundant for simple defaults.HasDefaultTrait to avoid repeating getDefault() logic.
trait HasDefault {
public function getDefault(): static {
return new static($this->defaultAttributes());
}
}
getDefault() is lazy-loaded via Laravel’s container to avoid performance pitfalls.How can I help you explore Laravel packages today?