graham-campbell/manager
Laravel Manager provides reusable manager functionality for Laravel apps. It helps you build driver-based services with a consistent API for creating, caching, and resolving implementations. Supports PHP 7.4–8.5 and Laravel 8–13.
Strengths:
Manager implementations (e.g., CacheManager, FilesystemManager), reducing cognitive overhead for developers familiar with Laravel’s ecosystem.extend() method enables runtime driver registration, critical for plugins or SaaS multi-tenancy (e.g., adding a custom Stripe driver without code changes).__call magic, improving performance for stateless operations (e.g., API calls).Weaknesses:
spatie/laravel-activitylog for auditing).Key Use Cases:
Manager::extend('analytics', CustomTool::class)).Manager-compatible facade.Laravel Ecosystem Fit:
Manager facade (e.g., Manager::connection('s3')->put()) for consistency with Laravel conventions.Manager::fake() or Manager::shouldReceive()).Non-Laravel PHP:
app() with a DI container).Existing Codebase Impact:
AbstractManager (e.g., swap new StripeService() for Manager::connection('stripe')).| Risk Area | Assessment | Mitigation Strategy |
|---|---|---|
| Connection Leaks | No built-in cleanup for stale connections (e.g., abandoned DB pools). | Implement Manager::disconnect() in critical paths or use Laravel’s app()->flush(). |
| Configuration Errors | Silent failures if invalid configs are provided (e.g., missing host). |
Add validation in createConnection() or use Laravel’s ValidatedConfig. |
| Performance | Connection pooling may not suit high-throughput stateless services. | Benchmark with Manager::reconnect() vs. fresh instantiation. |
| Async Limitations | No native support for async drivers (e.g., Guzzle HTTP clients). | Wrap drivers in Spatie\Async or use Manager::extend('http', fn() => new AsyncClient()). |
| Security | No built-in rate limiting or credential rotation. | Pair with laravel/sanctum or spatie/rate-limiter. |
| Testing Complexity | Mocking connections requires setup (e.g., Manager::shouldReceive()). |
Use Manager::fake() or Mockery for isolated tests. |
Architecture Alignment:
PaymentGatewayManager), or is it for new services?Extensibility Needs:
Manager::extend('stripe', ['api_key' => env('STRIPE_KEY')]))?Performance:
Observability:
Manager::connection('db')->retry(3))?Migration Path:
Security:
laravel/vault)?Team Skills:
Laravel Core:
Manager::connection('db') resolves PDO).config('services.stripe') for driver-specific settings.Manager as a facade (e.g., Manager::connection('s3')->put()) for consistency.ManagerEvents (e.g., ConnectionCreated, ConnectionFailed) for observability.Complementary Packages:
laravel/validation for config schemas.mockery/mockery or orchestra/testbench for connection mocking.spatie/async or reactphp for non-blocking drivers.monolog/monolog for connection lifecycle events.Anti-Patterns:
Manager as a singleton for stateful operations (e.g., WebSocket sessions).| Phase | Action | Tools/Examples |
|---|---|---|
| Assessment | Audit existing connection managers (e.g., PaymentGateway, StorageAdapter). |
grep -r "new StripeClient" app/ |
| Wrapper Creation | Extend AbstractManager for each service (e.g., StripeManager, S3Manager). |
php<br>class StripeManager extends AbstractManager {<br> protected function createConnection(array $config) {<br> return new \Stripe\StripeClient($config['api_key']);<br> }<br> protected function getConfigName() {<br> return 'services.stripe';<br> }<br>}<br> |
| Facade Exposure | Register facades for each manager (e.g., Stripe::charge()). |
php artisan make:facade Stripe |
| Driver Extension | Add runtime drivers via Manager::extend() (e.g., for plugins). |
php<br>Manager::extend('payment', fn() => new CustomPaymentGateway());<br> |
| Deprecation | Phase out old managers in favor of Manager-based ones. |
php<br>// Old<br>Payment::charge();<br>// New (v2)<br>Manager::connection('stripe')->charge();<br> |
| Testing | Mock connections in tests using Manager::fake() or shouldReceive(). |
php<br>Manager::shouldReceive('connection')->andReturn(new FakeStripe());<br> |
How can I help you explore Laravel packages today?