Zum Hauptinhalt springen

Was ist Manager?

Illuminate\Support\Manager ist eine abstrakte Klasse, die es seit Laravel 4.0 gibt. Sie stellt die Grundlage bereit, um Systeme zu bauen, in denen sich verschiedene „Treiber” für Cache, Session, Mail usw. einfach austauschen lassen. Ein „Treiber” ist ein Backend mit gleicher Schnittstelle, aber unterschiedlicher interner Implementierung. Bei Sessions z. B. gibt es die Treiber file, cookie, database, redis — umgeschaltet wird über den driver-Key in der Konfigurationsdatei.

Verwendung im Framework

Nicht jede Klasse mit dem Namen Manager erbt tatsächlich von Illuminate\Support\Manager.
KlasseErbt von Manager?
Illuminate\Session\SessionManager✅ Ja
Illuminate\Cache\CacheManager❌ Nein (Eigenimplementierung)
Illuminate\Queue\QueueManager❌ Nein (Eigenimplementierung)
Laravel\Socialite\SocialiteManager✅ Ja
Auch die nicht erbenden Klassen folgen demselben Grundprinzip der Erweiterung über extend(). Wer das Manager-Muster versteht, versteht daher auch weite Teile des Frameworks.

Grundlegende Funktionsweise

driver() — einen Treiber ermitteln

Der Aufruf von driver() löst den Treiber in folgender Reihenfolge auf. Im tatsächlichen Quellcode wird der Methodenname aus dem Treibernamen per Str::studly() zusammengesetzt.
// Aus 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.");
}
Der file-Treiber ruft also createFileDriver(), der Treiber my-custom ruft createMyCustomDriver().

extend() — einen eigenen Treiber registrieren

Übergeben Sie an extend() den Treibernamen und eine Closure, um einen eigenen Treiber zu registrieren. Als Argument erhält die Closure die Container-Instanz.
use Illuminate\Support\Facades\Session;

Session::extend('redis-cluster', function ($app) {
    return new RedisClusterSessionHandler(
        $app->make('redis'),
        $app['config']['session'],
    );
});
extend() bindet die Closure an $this, sodass Sie in ihr auf Properties und Methoden des Managers zugreifen können.
// Aus 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 — Delegation an den Default-Treiber

Manager implementiert __call; Methodenaufrufe, die es am Manager selbst nicht gibt, werden automatisch an den Default-Treiber delegiert.
public function __call($method, $parameters)
{
    return $this->driver()->$method(...$parameters);
}
Dadurch können Sie SessionManager::get('key') direkt am Manager aufrufen — die tatsächliche Arbeit erledigt der Treiber.

Beispielimplementierung SessionManager

Ein Blick in Illuminate\Session\SessionManager zeigt die praktische Verwendung von Manager.
namespace Illuminate\Session;

use Illuminate\Support\Manager;

class SessionManager extends Manager
{
    // Pflicht: Default-Treiber zurückgeben
    public function getDefaultDriver()
    {
        return $this->config->get('session.driver');
    }

    // file-Treiber erzeugen
    protected function createFileDriver()
    {
        return $this->createNativeDriver();
    }

    // database-Treiber erzeugen
    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
        ));
    }

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

Manager in einem eigenen Paket verwenden

Grundlegende Implementierung

Als Beispiel bauen wir einen Benachrichtigungsdienst als von Manager abgeleitete Klasse.
1

Von Manager ableitende Klasse erstellen

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

Im Service Provider registrieren

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

Einen eigenen Treiber ergänzen

// z. B. in AppServiceProvider::boot()

$manager = app(NotificationManager::class);

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

Nutzung

$manager = app(NotificationManager::class);

// Default-Treiber verwenden
$manager->send('Nachricht');

// Einen bestimmten Treiber wählen
$manager->driver('email')->send('Nachricht');

// Einmal aufgelöste Treiber werden gecacht
$manager->driver('slack'); // Gibt dieselbe Instanz zurück

MultipleInstanceManager

Illuminate\Support\MultipleInstanceManager wurde in Laravel 10 hinzugefügt. Während Manager die „Art” eines Treibers verwaltet, kann MultipleInstanceManager mehrere benannte „Instanzen” verwalten.

Unterschiede zu Manager

ManagerMultipleInstanceManager
VerwaltungseinheitTreibertypen (file, redis usw.)Benannte Instanzen (mailer1, mailer2 usw.)
KonfigurationEin Default-TreiberKonfiguration pro Instanz
HauptanwendungSession, Cache usw.Mail, Logs — Fälle mit mehreren Verbindungen
Zugriffsmethodedriver()instance()

Pflichtmethoden

Wer von MultipleInstanceManager ableitet, muss drei Methoden implementieren.
// Aus dem Quellcode
abstract public function getDefaultInstance();
abstract public function setDefaultInstance($name);
abstract public function getInstanceConfig($name);
getInstanceConfig() gibt das Konfigurationsarray zu einem Namen zurück. Die Konfiguration muss zwingend den Schlüssel driver (bzw. den mit $driverKey gesetzten Namen) enthalten.

Auflösungsablauf

Beispielimplementierung in einem eigenen Paket

Als Beispiel ein Paket, das mehrere SMS-Gateways parallel bedient.
namespace App\Sms;

use Illuminate\Support\MultipleInstanceManager;

class SmsManager extends MultipleInstanceManager
{
    // Name der Default-Instanz
    public function getDefaultInstance(): string
    {
        return $this->config->get('sms.default', 'primary');
    }

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

    // Konfiguration zum Instanznamen zurückgeben
    public function getInstanceConfig($name): array
    {
        return $this->config->get("sms.gateways.{$name}");
    }

    // twilio-Treiber erzeugen (Konfigurationsarray wird übergeben)
    protected function createTwilioDriver(array $config): TwilioSmsGateway
    {
        return new TwilioSmsGateway(
            $config['account_sid'],
            $config['auth_token'],
        );
    }

    // vonage-Treiber erzeugen
    protected function createVonageDriver(array $config): VonageSmsGateway
    {
        return new VonageSmsGateway(
            $config['api_key'],
            $config['api_secret'],
        );
    }
}
Zugehörige Konfigurationsdatei:
// 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'),
        ],
    ],
];
Die Nutzung erfolgt über instance() mit einem Namen.
$sms = app(SmsManager::class);

// Default-Instanz nutzen (primary = twilio)
$sms->send('+491701234567', 'Bestätigungscode: 123456');

// Instanz nach Name auswählen
$sms->instance('backup')->send('+491701234567', 'Bestätigungscode: 123456');

// Marketing-Instanz nutzen
$sms->instance('marketing')->send('+491701234567', 'Kampagnen-Info');
Wie Manager kann auch MultipleInstanceManager über extend() um eigene Treiber erweitert werden. Es implementiert ebenfalls __call, sodass unbekannte Methoden an die Default-Instanz delegiert werden.

Verwaltung des Treiber-Caches

Cache-Operationen von Manager

// Alle Treiber holen
$drivers = $manager->getDrivers();

// Cache aller Treiber leeren
$manager->forgetDrivers();

Cache-Operationen von MultipleInstanceManager

// Eine bestimmte Instanz löschen
$manager->forgetInstance('backup');

// Default-Instanz löschen
$manager->forgetInstance();

// Mehrere Instanzen auf einmal löschen
$manager->forgetInstance(['primary', 'backup']);

// Instanz löschen und Cache leeren
$manager->purge('backup');

Fazit

  • Manager verwaltet die „Art” eines Treibers. Sie implementieren createXxxDriver()-Methoden und erweitern per extend().
  • MultipleInstanceManager verwaltet „Instanzen” eines Treibers nach Name. Passend für Pakete mit mehreren Verbindungskonfigurationen.
  • Nicht jede Klasse mit dem Namen Manager erbt von Illuminate\Support\Manager. CacheManager und QueueManager sind eigene Implementierungen.

Macroable-Trait

Lernen Sie den Macroable-Trait kennen, mit dem Sie bestehenden Klassen eigene Methoden hinzufügen.
Zuletzt geändert am 13. Juli 2026