Passer au contenu principal

Qu’est-ce que Manager

Illuminate\Support\Manager est une classe abstraite présente depuis Laravel 4.0. Elle fournit les fondations permettant de construire simplement un système capable de basculer entre plusieurs « drivers », comme le cache, la session ou le mail. Un « driver » est un backend qui présente la même interface mais dont l’implémentation interne diffère. Par exemple, pour la session, on trouve les drivers file, cookie, database ou redis, sélectionnés via la clé driver du fichier de configuration.

Utilisation dans le framework

Toutes les classes appelées Manager n’héritent pas de Illuminate\Support\Manager.
ClasseHérite-t-elle de Manager ?
Illuminate\Session\SessionManager✅ Oui
Illuminate\Cache\CacheManager❌ Non (implémentation dédiée)
Illuminate\Queue\QueueManager❌ Non (implémentation dédiée)
Laravel\Socialite\SocialiteManager✅ Oui
Les classes qui n’en héritent pas suivent tout de même la même logique fondamentale d’extension via extend(). Comprendre le pattern Manager aide donc à comprendre le fonctionnement de tout le framework.

Principe de base

driver() — obtenir un driver

L’appel à driver() résout un driver selon les étapes suivantes. Dans le code source, le nom de la méthode est construit à partir du nom du driver via Str::studly().
// Extrait de Illuminate\Support\Manager::createDriver()
protected function createDriver($driver)
{
    if (isset($this->customCreators[$driver])) {
        return $this->callCustomCreator($driver);
    }

    $method = 'create'.Str::studly($driver).'Driver';

    if (method_exists($this, $method)) {
        return $this->$method();
    }

    throw new InvalidArgumentException("Driver [$driver] not supported.");
}
Autrement dit, le driver file appelle createFileDriver() et le driver my-custom appelle createMyCustomDriver().

extend() — enregistrer un driver personnalisé

Vous pouvez enregistrer votre propre driver en passant un nom et une closure à extend(). La closure reçoit l’instance du conteneur en argument.
use Illuminate\Support\Facades\Session;

Session::extend('redis-cluster', function ($app) {
    return new RedisClusterSessionHandler(
        $app->make('redis'),
        $app['config']['session'],
    );
});
extend() lie la closure à $this, ce qui permet d’accéder aux propriétés et méthodes du Manager depuis la closure.
// Extrait de Illuminate\Support\Manager::extend()
public function extend($driver, Closure $callback)
{
    try {
        $callback = $callback->bindTo($this, static::class) ?? throw new RuntimeException;
    } catch (Throwable) {
        $callback = $callback->bindTo(null, static::class);
    }

    $this->customCreators[$driver] = $callback;

    return $this;
}

__call — délégation au driver par défaut

La classe Manager implémente __call. Les appels de méthodes qui n’existent pas sur le Manager lui-même sont automatiquement délégués au driver par défaut.
public function __call($method, $parameters)
{
    return $this->driver()->$method(...$parameters);
}
C’est ce qui permet d’écrire SessionManager::get('key') en utilisant directement le Manager, tout en confiant le traitement effectif au driver.

Exemple d’implémentation : SessionManager

Illuminate\Session\SessionManager illustre concrètement l’utilisation de Manager.
namespace Illuminate\Session;

use Illuminate\Support\Manager;

class SessionManager extends Manager
{
    // Obligatoire : retourne le driver par défaut
    public function getDefaultDriver()
    {
        return $this->config->get('session.driver');
    }

    // Construction du driver file
    protected function createFileDriver()
    {
        return $this->createNativeDriver();
    }

    // Construction du driver database
    protected function createDatabaseDriver()
    {
        $table = $this->config->get('session.table');
        $lifetime = $this->config->get('session.lifetime');

        return $this->buildSession(new DatabaseSessionHandler(
            $this->getDatabaseConnection(), $table, $lifetime, $this->container
        ));
    }

    // Construction du driver redis
    protected function createRedisDriver()
    {
        $handler = $this->createCacheHandler('redis');
        // ...
        return $this->buildSession($handler);
    }
}

Utiliser Manager dans un package maison

Implémentation de base

Prenons un service de notifications pour créer une classe personnalisée héritant de Manager.
1

Créer une classe qui hérite de Manager

namespace App\Notifications;

use Illuminate\Support\Manager;

class NotificationManager extends Manager
{
    public function getDefaultDriver(): string
    {
        return $this->config->get('notifications.driver', 'slack');
    }

    protected function createSlackDriver(): SlackNotifier
    {
        return new SlackNotifier(
            $this->config->get('notifications.slack'),
        );
    }

    protected function createEmailDriver(): EmailNotifier
    {
        return new EmailNotifier(
            $this->config->get('notifications.email'),
        );
    }

    protected function createLogDriver(): LogNotifier
    {
        return new LogNotifier(
            $this->container->make('log'),
        );
    }
}
2

Enregistrer via un service provider

namespace App\Providers;

use App\Notifications\NotificationManager;
use Illuminate\Support\ServiceProvider;

class NotificationServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->singleton(NotificationManager::class, function ($app) {
            return new NotificationManager($app);
        });
    }
}
3

Ajouter un driver personnalisé

// Dans AppServiceProvider::boot() par exemple

$manager = app(NotificationManager::class);

$manager->extend('teams', function ($app) {
    return new TeamsNotifier(
        $app['config']['notifications.teams'],
    );
});
4

Utilisation

$manager = app(NotificationManager::class);

// Utiliser le driver par défaut
$manager->send('message');

// Spécifier un driver précis
$manager->driver('email')->send('message');

// Un driver résolu est mis en cache
$manager->driver('slack'); // renvoie la même instance

MultipleInstanceManager

Illuminate\Support\MultipleInstanceManager est une classe ajoutée dans Laravel 10. Là où Manager gère les « types » de drivers, MultipleInstanceManager gère plusieurs « instances » nommées.

Différences avec Manager

ManagerMultipleInstanceManager
Unité de gestionType de driver (file, redis, etc.)Instance nommée (mailer1, mailer2, etc.)
ConfigurationUn driver par défaut uniqueConfiguration par instance
Usage principalSession, cache, etc.Mail, log, etc. lorsqu’il faut plusieurs connexions
Méthode d’accèsdriver()instance()

Méthodes obligatoires

Pour hériter de MultipleInstanceManager, il faut implémenter trois méthodes.
// Extrait du code source
abstract public function getDefaultInstance();
abstract public function setDefaultInstance($name);
abstract public function getInstanceConfig($name);
getInstanceConfig() renvoie le tableau de configuration associé au nom. Ce tableau doit obligatoirement contenir la clé driver (ou la clé spécifiée par $driverKey).

Flot de résolution

Exemple d’implémentation dans un package maison

Prenons l’exemple d’un package prenant en charge simultanément plusieurs passerelles SMS.
namespace App\Sms;

use Illuminate\Support\MultipleInstanceManager;

class SmsManager extends MultipleInstanceManager
{
    // Nom de l'instance par défaut
    public function getDefaultInstance(): string
    {
        return $this->config->get('sms.default', 'primary');
    }

    public function setDefaultInstance($name): void
    {
        $this->config->set('sms.default', $name);
    }

    // Renvoie la configuration associée au nom d'instance
    public function getInstanceConfig($name): array
    {
        return $this->config->get("sms.gateways.{$name}");
    }

    // Construction du driver twilio (la config est passée en argument)
    protected function createTwilioDriver(array $config): TwilioSmsGateway
    {
        return new TwilioSmsGateway(
            $config['account_sid'],
            $config['auth_token'],
        );
    }

    // Construction du driver vonage
    protected function createVonageDriver(array $config): VonageSmsGateway
    {
        return new VonageSmsGateway(
            $config['api_key'],
            $config['api_secret'],
        );
    }
}
Fichier de configuration correspondant :
// config/sms.php
return [
    'default' => 'primary',

    'gateways' => [
        'primary' => [
            'driver' => 'twilio',
            'account_sid' => env('TWILIO_ACCOUNT_SID'),
            'auth_token' => env('TWILIO_AUTH_TOKEN'),
        ],
        'backup' => [
            'driver' => 'vonage',
            'api_key' => env('VONAGE_API_KEY'),
            'api_secret' => env('VONAGE_API_SECRET'),
        ],
        'marketing' => [
            'driver' => 'twilio',
            'account_sid' => env('TWILIO_MARKETING_SID'),
            'auth_token' => env('TWILIO_MARKETING_TOKEN'),
        ],
    ],
];
Utilisation : on désigne le nom via instance().
$sms = app(SmsManager::class);

// Utiliser l'instance par défaut (primary = twilio)
$sms->send('+33612345678', 'Code de confirmation : 123456');

// Cibler une instance par nom
$sms->instance('backup')->send('+33612345678', 'Code de confirmation : 123456');

// Utiliser l'instance dédiée au marketing
$sms->instance('marketing')->send('+33612345678', 'Annonce de campagne');
MultipleInstanceManager permet, comme Manager, d’ajouter des drivers personnalisés via extend(). Il implémente aussi __call, si bien que les méthodes absentes de l’instance elle-même sont déléguées à l’instance par défaut.

Gestion du cache de drivers

Manipulation du cache dans Manager

// Récupérer tous les drivers
$drivers = $manager->getDrivers();

// Vider le cache de tous les drivers
$manager->forgetDrivers();

Manipulation du cache dans MultipleInstanceManager

// Supprimer une instance spécifique
$manager->forgetInstance('backup');

// Supprimer l'instance par défaut
$manager->forgetInstance();

// Supprimer plusieurs instances d'un coup
$manager->forgetInstance(['primary', 'backup']);

// Supprimer une instance et purger son cache
$manager->purge('backup');

Résumé

  • Manager gère les « types » de drivers. Implémentez des méthodes createXxxDriver() et étendez avec extend().
  • MultipleInstanceManager gère les « instances » de drivers nommées. Adapté aux packages nécessitant plusieurs configurations de connexion.
  • Toutes les classes nommées Manager n’héritent pas de Illuminate\Support\Manager. CacheManager et QueueManager ont leur propre implémentation.

Trait Macroable

Découvrez l’utilisation du trait Macroable pour ajouter des méthodes personnalisées aux classes existantes.
Dernière modification le 13 juillet 2026