Implementation of the Manager pattern existing in Laravel framework.
| Manager | 3.* | 2.* | 1.* |
|---|---|---|---|
| php ^8.1 | ✅ | ❌ | ❌ |
| php 8.0.* | ✅ | ✅ | ❌ |
| php 7.* | ❌ | ❌ | ✅ |
composer require degraciamathieu/manager
This package offers an abstract class DeGraciaMathieu\Manager\Manager which needs to be extended to implement the creation of various Driver classes :
namespace App\Managers;
use DeGraciaMathieu\Manager\Manager;
class WeatherManager extends Manager {
public function createOpenweathermapDriver()
{
return new Openweathermap();
}
public function getDefaultDriver(): string
{
return 'openweathermap';
}
}A driver is a class integrating all the logic of an implementation, in our examples the interactions with the APIs of Openweathermap :
namespace App\Managers;
class Openweathermap {
public function itsRainingNow(string $city): bool
{
// call Openweathermap api to know if it is raining in this city
return true;
}
}From now on, you can directly call the method of a driver directly from the manager :
(new WeatherManager())->itsRainingNow('Paris'); // trueThe manager will call the itsRainingNow method of the default driver configured by the getDefaultDriver method.
You can also call any driver from the manager's driver method :
(new WeatherManager())->driver('openweathermap')->itsRainingNow('Paris');Now if you want to create a new implementation, for example if you want to use Aerisweather APIs, you just have to create a new driver in your manager :
namespace App\Managers;
use DeGraciaMathieu\Manager\Manager;
class WeatherManager extends Manager {
public function createOpenweathermapDriver()
{
return new Openweathermap();
}
public function createAerisweatherDriver()
{
return new Aerisweather();
}
public function getDefaultDriver(): string
{
return 'openweathermap';
}
}Tip, the
getDefaultDrivermethod is the perfect place to use a configuration or environment variable !
For more consistency it is advisable to implement an interface to the different drivers :
namespace App\Managers;
interface Driver {
public function itsRainingNow(string $city): bool;
}You obviously need to add this interface to your drivers.
namespace App\Managers;
use DeGraciaMathieu\Manager\Manager;
class WeatherManager extends Manager {
public function createOpenweathermapDriver(): Driver
{
return new Openweathermap();
}
public function createAerisweatherDriver(): Driver
{
return new Aerisweather();
}
public function getDefaultDriver(): string
{
return 'openweathermap';
}
}Now you will be assured that each driver instantiated by the manager will have the same interface.
To control side effects of drivers, it is advisable to create a class encapsulating the instance of a driver, this class is usually called Repository :
namespace App\Managers;
use DeGraciaMathieu\Manager\Manager;
class WeatherManager extends Manager {
public function createOpenweathermapDriver(): Repository
{
$driver = new Openweathermap();
return new Repository($driver);
}
public function createAerisweatherDriver(): Repository
{
$driver = new Aerisweather();
return new Repository($driver);
}
public function getDefaultDriver(): string
{
return 'openweathermap';
}
}The repository is a class providing a bridge between your application and the driver :
namespace App\Managers;
class Repository {
public function __construct(
private Driver $driver,
){}
public function itsRainingNow(string $city): bool
{
return $this->driver->itsRainingNow($city);
}
}This repository class is an anti-corruption layer
Thus, your application will never be aware of which driver it is handling, because it will always be encapsulated in a class repository.
The repository is also a good place if you need to add specific logic for all drivers.
You can also cache the creation of Drivers with the $singleton property.
With the singleton property you will only create one instance of Openweathermap driver :
<?php
$weatherManager = new WeatherManager(singleton: true);
$weatherManager->driver('openweathermap')->itsRainingNow('Paris');
$weatherManager->driver('openweathermap')->itsRainingNow('Paris');
$weatherManager->driver('openweathermap')->itsRainingNow('Paris');by default, singleton property value is False
Usage example of the pattern manager in a Laravel project.

