degraciamathieu / manager
Implementation of the Manager pattern existing in Laravel framework.
Installs: 31 303
Dependents: 2
Suggesters: 0
Security: 0
Stars: 88
Watchers: 3
Forks: 2
Open Issues: 0
Requires
- php: ^8.1
Requires (Dev)
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^9.0
- symfony/var-dumper: ^6.3
README
DeGraciaMathieu/Manager
Implementation of the Manager pattern existing in Laravel framework.
Installation
composer require degraciamathieu/manager
Usage
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'); // true
The 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
getDefaultDriver
method is the perfect place to use a configuration or environment variable !
Add an interface to the drivers
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.
Repository class
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.
Work with singleton
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
Example with Laravel
Usage example of the pattern manager in a Laravel project.