Saltar al contenido principal

Qué es Manager

Illuminate\Support\Manager es una clase abstracta presente en Laravel desde la versión 4.0. Proporciona la base para construir con facilidad sistemas donde puedes alternar entre varios “drivers”, como caché, sesión o correo. Por «driver» entendemos backends que comparten una misma interfaz pero cuya implementación interna difiere. Por ejemplo, en sesiones existen file, cookie, database y redis, y se cambian mediante la clave driver del archivo de configuración.

Uso dentro del framework

No todas las clases con nombre Manager extienden Illuminate\Support\Manager.
Clase¿Extiende Manager?
Illuminate\Session\SessionManager✅ Sí.
Illuminate\Cache\CacheManager❌ No (implementación propia).
Illuminate\Queue\QueueManager❌ No (implementación propia).
Laravel\Socialite\SocialiteManager✅ Sí.
Aun así, las clases que no lo heredan comparten la idea básica de extenderse con extend(). Entender el patrón Manager te ayudará a comprender cómo funciona el framework en general.

Funcionamiento básico

driver() — obtener un driver

Cuando llamas a driver(), se resuelve siguiendo estos pasos: Si miras el código fuente, verás que el nombre del método se construye a partir del nombre del driver con Str::studly().
// 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.");
}
Por tanto, el driver file invoca createFileDriver() y el driver my-custom invoca createMyCustomDriver().

extend() — registrar un driver personalizado

Pasando el nombre del driver y una closure a extend(), puedes registrar tu propio driver. El argumento de la closure es la instancia del contenedor.
use Illuminate\Support\Facades\Session;

Session::extend('redis-cluster', function ($app) {
    return new RedisClusterSessionHandler(
        $app->make('redis'),
        $app['config']['session'],
    );
});
extend() hace un bind del closure a $this, así que dentro puedes acceder a las propiedades y métodos del Manager.
// 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 — delegación al driver por defecto

La clase Manager implementa __call, así que cualquier llamada a un método que no exista en el propio Manager se delega automáticamente al driver por defecto.
public function __call($method, $parameters)
{
    return $this->driver()->$method(...$parameters);
}
Esto es lo que permite hacer cosas como SessionManager::get('key'): usas directamente el Manager, pero el trabajo real lo hace el driver.

Ejemplo con SessionManager

Si miras Illuminate\Session\SessionManager, verás claramente cómo se usa Manager.
namespace Illuminate\Session;

use Illuminate\Support\Manager;

class SessionManager extends Manager
{
    // Obligatorio: devuelve el driver por defecto
    public function getDefaultDriver()
    {
        return $this->config->get('session.driver');
    }

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

    // Crea el 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
        ));
    }

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

Usar Manager en tu paquete

Implementación básica

Como ejemplo, creemos una clase de servicio de notificaciones que extiende Manager.
1

Crear una clase que extienda 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

Registrar en 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

Añadir un driver personalizado

// En AppServiceProvider::boot() u otro sitio

$manager = app(NotificationManager::class);

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

Usarlo

$manager = app(NotificationManager::class);

// Usa el driver por defecto
$manager->send('Mensaje');

// Especifica un driver concreto
$manager->driver('email')->send('Mensaje');

// Una vez resuelto, el driver queda cacheado
$manager->driver('slack'); // devuelve la misma instancia

MultipleInstanceManager

Illuminate\Support\MultipleInstanceManager es una clase añadida en Laravel 10. Mientras que Manager gestiona «tipos» de driver, MultipleInstanceManager gestiona varias «instancias» con nombre.

Diferencias respecto a Manager

ManagerMultipleInstanceManager
Unidad gestionadaTipos de driver (file, redis, etc.)Instancias con nombre (mailer1, mailer2, etc.)
ConfiguraciónUn único driver por defectoCada instancia tiene su propia configuración
Usos habitualesSesiones, caché, etc.Correo, log, cualquier cosa que requiera varias conexiones
Método de obtencióndriver()instance()

Métodos obligatorios

Al extender MultipleInstanceManager, debes implementar tres métodos.
// Del código fuente
abstract public function getDefaultInstance();
abstract public function setDefaultInstance($name);
abstract public function getInstanceConfig($name);
getInstanceConfig() devuelve el array de configuración correspondiente al nombre. La configuración debe contener siempre la clave driver (o la clave que hayas especificado con $driverKey).

Flujo de resolución

Ejemplo en un paquete propio

Como ejemplo, un paquete que soporta varias gateways SMS a la vez.
namespace App\Sms;

use Illuminate\Support\MultipleInstanceManager;

class SmsManager extends MultipleInstanceManager
{
    // Nombre de la instancia por defecto
    public function getDefaultInstance(): string
    {
        return $this->config->get('sms.default', 'primary');
    }

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

    // Devuelve la configuración del nombre indicado
    public function getInstanceConfig($name): array
    {
        return $this->config->get("sms.gateways.{$name}");
    }

    // Crea el driver twilio (recibe el array de configuración)
    protected function createTwilioDriver(array $config): TwilioSmsGateway
    {
        return new TwilioSmsGateway(
            $config['account_sid'],
            $config['auth_token'],
        );
    }

    // Crea el driver vonage
    protected function createVonageDriver(array $config): VonageSmsGateway
    {
        return new VonageSmsGateway(
            $config['api_key'],
            $config['api_secret'],
        );
    }
}
Archivo de configuración correspondiente:
// 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'),
        ],
    ],
];
En el uso, indica el nombre con instance().
$sms = app(SmsManager::class);

// Usa la instancia por defecto (primary = twilio)
$sms->send('+34600000000', 'Código: 123456');

// Especifica la instancia por nombre
$sms->instance('backup')->send('+34600000000', 'Código: 123456');

// Usa la instancia de marketing
$sms->instance('marketing')->send('+34600000000', 'Aviso de campaña');
MultipleInstanceManager permite añadir drivers personalizados con extend(), igual que Manager. También implementa __call, así que los métodos que no existen en el propio Manager se delegan a la instancia por defecto.

Gestión de la caché de drivers

Operaciones de caché en Manager

// Obtiene todos los drivers
$drivers = $manager->getDrivers();

// Limpia la caché de todos los drivers
$manager->forgetDrivers();

Operaciones de caché en MultipleInstanceManager

// Elimina una instancia concreta
$manager->forgetInstance('backup');

// Elimina la instancia por defecto
$manager->forgetInstance();

// Elimina varias instancias a la vez
$manager->forgetInstance(['primary', 'backup']);

// Elimina la instancia y purga la caché
$manager->purge('backup');

Resumen

  • Manager gestiona «tipos» de driver. Implementa los métodos createXxxDriver() y extiende con extend().
  • MultipleInstanceManager gestiona «instancias» de drivers por nombre. Es adecuado para paquetes que necesitan varias configuraciones de conexión.
  • No todas las clases con nombre Manager extienden Illuminate\Support\Manager. CacheManager y QueueManager tienen implementaciones propias.

Trait Macroable

Aprende cómo usar el trait Macroable para añadir métodos propios a clases existentes.
Última modificación el 13 de julio de 2026