imanghafoori/laravel-smart-facades
Installation:
composer require imanghafoori/laravel-smart-facades
Publish the config (optional):
php artisan vendor:publish --provider="Imanghafoori\SmartFacades\SmartFacadesServiceProvider"
First Use Case:
Replace a standard facade call (e.g., Cache::get('key')) with a context-aware approach:
// Standard facade
Cache::get('key');
// Smart Facade (context-aware)
Cache::context('user')->get('key'); // Resolves to a specific cache driver/key based on context
Key Files:
config/smart-facades.php (for configuration)app/Providers/SmartFacadesServiceProvider.php (for custom strategies)Context-Based Resolution: Use contexts to dynamically resolve facade behavior (e.g., cache drivers, database connections, queues).
// Resolve to 'redis' driver for 'user' context
Cache::context('user')->get('preferences');
// Fallback to default if no context strategy exists
Cache::context('unknown')->get('key'); // Uses default driver
Strategy Pattern Integration:
Define custom strategies for facades (e.g., Cache, DB, Queue).
// In SmartFacadesServiceProvider.php
public function register()
{
$this->app->singleton('cache.context.user', function ($app) {
return Cache::extend('redis');
});
}
Chaining and Method Overrides: Extend facade methods with context-aware logic:
// Override 'get' for 'user' context
Cache::context('user')->get('key', function () {
return 'default_value';
});
Dynamic Facade Aliases: Use aliases for context-specific facades:
// In config/smart-facades.php
'aliases' => [
'UserCache' => 'cache.context.user',
];
// Usage
UserCache::get('key'); // Resolves to 'cache.context.user'
Middleware for Facades: Apply middleware to facade calls (e.g., logging, rate-limiting):
Cache::context('user')->middleware([LogCacheAccess::class])->get('key');
Leverage Existing Facades:
Works seamlessly with Laravel’s built-in facades (Cache, DB, Queue, Auth, etc.).
Example:
DB::context('tenant')->table('users')->get();
Custom Facade Extension:
Extend third-party facades (e.g., Spatie\Permission):
// In SmartFacadesServiceProvider.php
$this->app->singleton('permission.context.admin', function ($app) {
return new PermissionService($app['permission'], 'admin');
});
Testing: Mock context-specific facades in tests:
$this->app->instance('cache.context.user', Mockery::mock('overload:Cache'));
Performance: Cache context resolutions if strategies are static:
Cache::context('user')->remember('key', 60, function () {
return Cache::context('user')->get('expensive_key');
});
Context Resolution Order:
Cache::context('a')->context('b')->get('key') resolves b first.Circular Dependencies:
Avoid recursive context resolutions (e.g., Cache::context('user')->get('cache.context.user')).
Fix: Use dependency injection or static strategies.
Middleware Stack Bloat: Overusing middleware can degrade performance. Fix: Limit middleware to critical paths or use decorators.
Facade Overrides:
Overriding core facade methods (e.g., Cache::get) may conflict with Laravel’s internal calls.
Fix: Prefix custom methods (e.g., Cache::contextGet('key')).
Configuration Cache: After publishing config, clear Laravel’s config cache:
php artisan config:clear
Log Context Resolutions:
Enable debug mode in config/smart-facades.php:
'debug' => env('APP_DEBUG', false),
Logs context resolution steps to storage/logs/laravel.log.
Inspect Strategies: Dump registered strategies:
dd(app()->make('cache.context.user'));
Fallback Behavior:
Ensure default facades are configured in config/smart-facades.php:
'defaults' => [
'cache' => 'file',
'db' => 'mysql',
],
Custom Context Providers: Dynamically generate contexts from request data:
// In SmartFacadesServiceProvider.php
$this->app->singleton('cache.context.dynamic', function ($app) {
return Cache::extend(request('tenant') ?? 'default');
});
Facade Events: Dispatch events for context changes:
Cache::context('user')->get('key'); // Triggers `CacheContextChanged` event
API Integration: Use contexts for API versioning or tenant isolation:
DB::context('api.v2')->table('users')->get();
CLI Contexts: Set contexts via artisan commands:
// In a command
$this->app->singleton('cache.context.cli', function () {
return Cache::extend('array');
});
Testing Utilities:
Add helper methods to phpunit.xml or TestCase:
// In TestCase.php
protected function withContext($context)
{
$this->app->instance("cache.context.$context", Cache::extend('array'));
}
How can I help you explore Laravel packages today?