La notion de Manager dans Laravel
Introduction à un élément incontournable au cœur de Laravel, le Manager. Ce dernier est au commande d’un bon nombre des services.
A quoi sert-il ?
Le Manager a pour rôle la création de Driver ayant leur propre implémentation d’un service.
Les différentes implémentations du Driver sont liées par une interface afin de rendre les mêmes fonctionnalités disponibles à l’utilisation d’un service.
La configuration du service permet de spécifier un Driver par défaut mais il est tout à fait possible d’appeler explicitement un Driver particulier depuis le Manager.
Comment fonctionne-t-il ?
On va prendre pour exemple le service de Cache de Laravel.
La configuration du service
On commence par explorer le fichier config/cache.php qui détail la configuration du service :
1return [ 2 'default' => env('CACHE_DRIVER', 'file'), 3 4 'stores' => [ 5 'array' = [ 6 // ... 7 ], 8 'file' => [ 9 // ...10 ],11 // ...12 ],13];
On retrouve la déclaration de l’implémentation par défaut du service, définit par la variable d’env CACHE_DRIVER qui vaut file par défaut, on distingue aussi les stores qui sont les implémentations disponibles du service, ici array et file.
Chacune des implémentations dispose ensuite de leur propre configuration, exemple avec file :
1'file' => [2 'driver' => 'file',3 'path' => storage_path('framework/cache/data'),4],
A noter la clé driver qui définit le nom de l’implémentation et qui a souvent pour valeur le nom du Driver. Pour ce qui est de la configuration spécifique de file on retrouve le chemin de stockage de l’information détenu dans la clé path.
La classe Manager
Ensuite, on visite le coeur du système, soit la classe Illuminate\Cache\CacheManager :
1namespace Illuminate\Cache; 2 3class CacheManager implements FactoryContract 4{ 5 /** 6 * The application instance. 7 * 8 * @var \Illuminate\Contracts\Foundation\Application 9 */10 protected $app;11 12 public function __construct($app)13 {14 $this->app = $app;15 }16 17 protected function resolve($name)18 {19 // ...20 }21 22 /**23 * Create an instance of the array cache driver.24 *25 * @param array $config26 * @return \Illuminate\Cache\Repository27 */28 protected function createArrayDriver(array $config)29 {30 return $this->repository(new ArrayStore($config['serialize'] ?? false));31 }32 33 /**34 * Create an instance of the file cache driver.35 *36 * @param array $config37 * @return \Illuminate\Cache\Repository38 */39 protected function createFileDriver(array $config)40 {41 return $this->repository(new FileStore($this->app['files'], $config['path'], $config['permission'] ?? null));42 }43 44 // ...45}
On met le focus sur les éléments clés de cette classe :
- Le manager dispose d’une instance d’
appqui permet l’accès à tous les autres services dont peut avoir besoin unDriver. - La méthode
resolves’occupe, à partir du nom d’unDriver, de récupérer la config spécifique et d’appeler la méthode dédiée de création du Driver exemple :createFileDriver. - Les méthodes de création des
Drivers, préfixé parcreate, qui se charge d’instancier unDriverspécifique en lui injectant ses dépendances et sa config.
A noter qu’on retrouve ici la notion de Repository qui encapsule le Driver. L’utilité du Repository est de faire du traitement commun entre tous les drivers, comme le déclenchement d’événements.
Le rôle du Driver
En bout de chaîne on retrouve le Driver, mais plutôt que de voir une implémentation spécifique, on va survoler le contrat qui les lie, soit l’interface Illuminate\Contracts\Cache\Store :
1namespace Illuminate\Contracts\Cache; 2 3interface Store 4{ 5 public function get($key); 6 7 public function many(array $keys); 8 9 public function put($key, $value, $seconds);10 11 public function putMany(array $values, $seconds);12 13 public function increment($key, $value = 1);14 15 public function decrement($key, $value = 1);16 17 public function forever($key, $value);18 19 public function forget($key);20 21 public function flush();22 23 public function getPrefix();24}
L’intérêt de cette interface est qu’elle détaille ce qui est indispensable à implémenter pour un Driver et aussi de faire du typage fort dans les classes qui sont dépendantes au service dans le cas où on ne dispose pas de la surcouche Repository.
Aller plus loin
Il est possible de créer sa propre implémentation d’un service, la doc Laravel propose un exemple au sujet du service Cache.
Mathieu De Gracia a développé un paquet qui propose l’intégration de nouveau service en utilisant la logique du Manager
A lire
Autres articles de la même catégorie
PHPStan valide nos règles de conception
Comment s’assurer du respect de nos règles de conception ? Avec PHPStan bien sûr !
William Suppo
Tour d'horizon des façades
Présentation du fonctionnement des façades, leurs avantages et inconvénients. Pourquoi faut-il les considérer dans un écosystème Laravel ?
Marc COLLET
À quoi sert le TrustProxies ?
Connaissez-vous le middleware TrustProxies ? Essentiel quand vous utilisez un proxy ou un load balancer, essayons de comprendre son fonctionnement !
Mathieu De Gracia