Building your own facade
Concept
Building a custom Facade gives your package or application code a clean static interface to a container-bound service. The process is: create a service class, bind it in a service provider, create a Facade class with getFacadeAccessor(), register the alias.
Steps to create a Facade:
- Create the service class (
app/Services/Cart.php). - Bind it in a service provider (
AppServiceProvider::register()). - Create a Facade class (
app/Facades/Cart.php) extendingIlluminate\Support\Facades\Facade. - Implement
getFacadeAccessor()returning the container key. - Register the alias in
config/app.php'saliasesarray (optional — for short names).
PHPDoc for IDE support: Without type hints, IDEs don't know what methods the Facade proxies. Add @method annotations to the Facade class, or install barryvdh/laravel-ide-helper and run php artisan ide-helper:generate.
Facade testing: Because the Facade resolves from the container, calling Cart::swap(new MockCart()) in tests replaces the underlying instance. Or use Cart::shouldReceive() via Mockery.
When to create a Facade: When you have a service that's used frequently across many places (controllers, views, blade components), and DI injection would add noise. Don't create Facades for rarely-used services.
Code Example
<?php
// 1. Service class
namespace App\Services;
class Cart
{
private array $items = [];
public function add(int $productId, int $quantity = 1): void
{
$this->items[$productId] = ($this->items[$productId] ?? 0) + $quantity;
}
public function remove(int $productId): void
{
unset($this->items[$productId]);
}
public function total(): int
{
return array_sum(array_map(fn($qty, $id) => Product::find($id)->price * $qty,
$this->items, array_keys($this->items)
));
}
public function count(): int
{
return array_sum($this->items);
}
public function items(): array { return $this->items; }
public function clear(): void { $this->items = []; }
}<?php
// 2. Bind in AppServiceProvider
$this->app->singleton(\App\Services\Cart::class, fn() => new \App\Services\Cart());<?php
// 3. Facade class
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
/**
* @method static void add(int $productId, int $quantity = 1)
* @method static void remove(int $productId)
* @method static int total()
* @method static int count()
* @method static array items()
* @method static void clear()
* @see \App\Services\Cart
*/
class Cart extends Facade
{
protected static function getFacadeAccessor(): string
{
return \App\Services\Cart::class;
}
}// 4. Alias in config/app.php
'aliases' => \Illuminate\Support\Facades\Facade::defaultAliases()->merge([
'Cart' => App\Facades\Cart::class,
])->toArray(),// 5. Usage anywhere
use App\Facades\Cart; // or just Cart:: if alias registered
Cart::add(productId: 42, quantity: 2);
echo Cart::count(); // 2
echo Cart::total(); // sum of items