Facades
Static interface for accessing Laravel services
Facades provide a static interface for accessing Laravel services. This pattern allows you to have static access to container services, while actually using Service Container.
Benefits of Facades:
- Cleaner and more readable code with simpler syntax
- Easy access to services without needing dependency injection
- Better testability with ability to mock
- Reduced boilerplate code
- Familiar API for developers
How it Works:
Facades use magic method __callStatic to forward calls to the real instance in Service Container. When you call Cache::get('key'), Laravel automatically resolves the related instance from container.
Common Laravel Facades Examples:
- <code>Cache::get()</code>, <code>Cache::put()</code> - for cache operations
- <code>DB::table()</code>, <code>DB::select()</code> - for database operations
- <code>Auth::user()</code>, <code>Auth::check()</code> - for authentication
- <code>Route::get()</code>, <code>Route::post()</code> - for route definition
- <code>Mail::send()</code> - for email sending
- <code>Queue::push()</code> - for queue operations
Comparison with Dependency Injection:
Facades are easier but Dependency Injection is better for testability and maintainability. In Laravel 11.x, using Contracts (interfaces) with DI is preferred.
Examples
Using Facade
use Illuminate\Support\Facades\Cache;
Cache::put('key', 'value', 3600);
$value = Cache::get('key');
Instead of using Service Container directly, we use Facade.
Creating Custom Facade
<?php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class PaymentGateway extends Facade
{
protected static function getFacadeAccessor()
{
return 'PaymentGateway';
}
}
A custom Facade that points to PaymentGateway in Container.
Using Facade in Controller
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
class UserController extends Controller
{
public function index()
{
$users = Cache::remember('users', 3600, function () {
return DB::table('users')->get();
});
return view('users.index', compact('users'));
}
}
Using Facades for easy access to cache and database.
Facade Mocking in Tests
<?php
namespace Tests\Feature;
use Illuminate\Support\Facades\Cache;
use Tests\TestCase;
class UserTest extends TestCase
{
public function test_user_caching()
{
Cache::shouldReceive('get')
->once()
->with('user.1')
->andReturn(['id' => 1, 'name' => 'John']);
$user = Cache::get('user.1');
$this->assertEquals('John', $user['name']);
}
}
You can mock Facades in tests.
Facade with Real-time Facades
<?php
// Instead of creating a Facade class, use real-time facade
use Facades\App\Services\PaymentGateway;
class OrderController extends Controller
{
public function process()
{
// PaymentGateway is automatically resolved from container
$result = PaymentGateway::charge(100);
return $result;
}
}
// In Service Provider:
app()->singleton('App\Services\PaymentGateway', function ($app) {
return new StripePaymentGateway();
});
Real-time Facades allow you to use Facade without creating Facade class.
Facade Root Access
<?php
use Illuminate\Support\Facades\Cache;
// Get underlying instance
$cache = Cache::getFacadeRoot();
// Check if facade is resolved
if (Cache::resolved()) {
// Facade has been resolved
}
// Get facade accessor name
$accessor = Cache::getFacadeAccessor();
You can access underlying instance and facade metadata.
Facade vs Dependency Injection
<?php
// Using Facade
use Illuminate\Support\Facades\Cache;
class UserService
{
public function getUser($id)
{
return Cache::remember("user.{$id}", 3600, function () use ($id) {
return User::find($id);
});
}
}
// Using Dependency Injection (Preferred)
use Illuminate\Contracts\Cache\Repository as Cache;
class UserService
{
public function __construct(private Cache $cache) {}
public function getUser($id)
{
return $this->cache->remember("user.{$id}", 3600, function () use ($id) {
return User::find($id);
});
}
}
Dependency Injection is better for testability and maintainability, but Facades are easier.
Facade Aliases
<?php
// In config/app.php
'aliases' => [
'Cache' => Illuminate\Support\Facades\Cache::class,
'DB' => Illuminate\Support\Facades\DB::class,
'Auth' => Illuminate\Support\Facades\Auth::class,
],
// Now you can use without full namespace
use Cache;
Cache::get('key');
// Or even without use statement (if alias is registered)
\Cache::get('key');
You can define aliases for Facades to make usage easier.
Use Cases
- Quick and easy access to Laravel services in controllers and views
- Usage in route closures for quick operations
- Usage in blade templates for helper functions
- Prototyping and rapid development
- Legacy code migration requiring static access
- Usage in console commands for quick access
Common Mistakes
- Using Facades instead of Dependency Injection in service classes reducing testability
- Using Facades in business logic causing tight coupling
- Forgetting to import Facade causing errors
- Using Facades in queue jobs which have different container instance
- Not mocking Facades in tests causing integration tests instead of unit tests
- Using Facades for everything which is overuse
Best Practices
- Use Dependency Injection for service classes (preferred)
- Use Facades for quick operations in controllers
- Always mock Facades in tests
- Use Contracts (interfaces) instead of Facades in dependency injection
- Use real-time Facades for classes that don't have Facade class
- Document Facades if creating custom Facade
Edge Cases
- Facades in queue jobs which have different container instance
- Facades in console commands which may have different context
- Facades in event listeners which may be resolved at different times
- Facades with circular dependencies
- Facades in testing requiring proper mocking
Performance Notes
- Facades overhead is very low and negligible
- Facade resolution with caching in production improves performance
- Using Facades has no negative impact on performance
- Real-time Facades may be slightly slower but negligible
Security Notes
- Ensure Facades use trusted sources
- Use Facades for sensitive operations with caution
- Ensure Facade accessor is properly bound
Interview Points
- What is the difference between Facade and Dependency Injection?
- How do Facades work?
- When should you use Facades and when DI?
- How can you mock Facade in tests?
- What are the benefits and drawbacks of using Facades?
- What are Real-time Facades and how do they work?
Version Notes
- Laravel 11.x: Improved performance in Facade resolution
- Laravel 11.x: Better support for real-time Facades
- Laravel 10.x: Improved Facade mocking in tests
- Laravel 9.x: Improved caching for Facades