Laravel’s Manager pattern is a clean and scalable solution for handling multiple providers behind a unified API. This article demonstrates how to build a configurable invoice driver system in Laravel using Billingo and PDF drivers. The implementation includes configuration files, interfaces, drivers, a manager class, service provider registration, and facade usage. The pattern provides easy extensibility, centralized configuration, and a consistent API across multiple providers.
In Hungary, there are many invoice providers such as Billingo or Számlázz.hu. In many projects, clients want the flexibility to choose which invoice provider they use.
To make switching providers easy and configurable, Laravel’s Manager pattern is an excellent solution. Laravel internally uses this pattern for cache, mail, queue, and filesystem drivers.
In this article, I will show you how to build a simple invoice driver system using Laravel Managers.
Create the configuration file
Create a new config file called config/invoice.php.
<?php
return [
/*
|--------------------------------------------------------------------------
| Default invoice driver
|--------------------------------------------------------------------------
|
| Supported drivers: pdf, billingo
|
*/
'driver' => env('INVOICE_DRIVER', 'pdf'),
];
Now you can change the default driver directly from your .env file.
INVOICE_DRIVER=pdf
or
INVOICE_DRIVER=billingo
Create the Driver Interface
Create the interface at app/Drivers/InvoiceInterface.php.
<?php
namespace App\Drivers;
interface InvoiceInterface
{
public function create(array $data): mixed;
}
The interface ensures that every driver follows the same API.
Create the Billingo Driver
Create app/Drivers/Billingo.php.
<?php
namespace App\Drivers;
class Billingo implements InvoiceInterface
{
public function create(array $data): mixed
{
// Create invoice using Billingo API
return true;
}
}
Create the PDF Driver
Create app/Drivers/PDF.php.
<?php
namespace App\Drivers;
class PDF implements InvoiceInterface
{
public function create(array $data): mixed
{
// Generate PDF invoice
return true;
}
}
Create the Invoice Manager
Create app/Managers/InvoiceManager.php.
<?php
namespace App\Managers;
use App\Drivers\Billingo;
use App\Drivers\PDF;
use Illuminate\Support\Manager;
class InvoiceManager extends Manager
{
public function createBillingoDriver(): Billingo
{
return $this->container->make(Billingo::class);
}
public function createPdfDriver(): PDF
{
return $this->container->make(PDF::class);
}
public function getDefaultDriver(): string
{
return $this->config->get('invoice.driver');
}
}
The Manager class automatically resolves drivers through the driver() method.
For example:
app('invoice')->driver('billingo');
internally calls:
createBillingoDriver()
Register the Manager
Register the manager inside app/Providers/AppServiceProvider.php.
<?php
namespace App\Providers;
use App\Managers\InvoiceManager;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->singleton('invoice', function ($app) {
return new InvoiceManager($app);
});
}
}
Create the Facade
Create app/Facades/Invoice.php.
<?php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
/**
* @method static mixed create(array $data)
* @method static mixed driver(string|null $driver = null)
*/
class Invoice extends Facade
{
protected static function getFacadeAccessor(): string
{
return 'invoice';
}
}
Usage
Now you can use the invoice service anywhere in your application.
use App\Facades\Invoice;
Invoice::create($data);
Laravel will automatically use the default driver configured in the config file.
Switch Driver Dynamically
You can also switch drivers dynamically at runtime.
Invoice::driver('billingo')->create($data);
or
Invoice::driver('pdf')->create($data);
Why use the Manager pattern?
The Manager pattern provides several advantages:
Easy driver switching
Centralized configuration
Clean abstraction layer
Extensible architecture
Better testability
Consistent API across providers
Adding a new invoice provider becomes very simple. Just create a new driver class and register it inside the manager.
Conclusion
Laravel’s Manager pattern is a clean and scalable solution for handling multiple providers behind a unified API.
It is especially useful for:
Invoice providers
Payment gateways
SMS providers
Cloud storage providers
Email services
If your application needs interchangeable providers, Laravel Managers are an excellent choice.