Managers

When we build our driver-based components, we need a way to manage them. We want to be able to create multiple predefined drivers or even create them at a later time during the application’s lifecycle. We want to be able to request instances of a particular driver and also have a fallback driver where calls are proxied into, for when we don’t specify a driver. This is the job of a Manager.

The manager is an entity that manages the creation of driver-based components. It is responsible for creating specific driver implementation based on an application’s configuration.

The manager is designed around the idea that components can have multiple drivers (instances of a component that are implemented differently). Using a manager, a component can define the logic that is needed to create drivers it supports. The manager acts as a hub for created and custom drivers of a component and it’s the gateway into the component.

As previously mentioned, laravel ships with support for managers and we want to leverage that to create our driver-based components. Let’s get into more details about how the manager works.

The Manager Class

Laravel provides an abstract Manager class in the Support namespace ( Illuminate\Support\Manager ). This class defines useful methods to help us manage our drivers. To get started, you extend the manager class and define driver creation methods in the subclass (your component’s manager class).

use Illuminate\Support\Manager; class FooManager extends Manager

{

//

}

Creating Drivers

Of course, creating a driver-based component requires us to be able to create drivers. The manager class defines a createDriver($driver) method that does exactly what it says on the tin, create a new driver instance. The method accepts a single argument; the name of the driver to create. It makes the assumption that the extending class has defined creational methods that create the drivers. These creational methods should have the following signature:

create[Drivername]Driver()

where Drivername is the name of the driver after it has been studly-cased.

The driver creation methods you define in your manager class should return an instance of the driver.

Obtaining a Driver

It’s like ordering an Uber, you get an instance of the manager and call the driver($driver = null) method on it. The base manager provides this method and it accepts a single optional argument; the name of the driver whose instance you want to obtain. The manager then goes and make the driver for you by calling the appropriate driver creation method you have defined in your manager class. If you don’t pass the name of the driver you want to obtain to the driver($driver = null) method, it returns an instance of the default driver.

The Fallback Driver

The manager is an abstract class and declares an abstract getDefaultDriver() method that must be defined by the extending manager class. This method should return the name of the default driver that should be used by the component when no driver is specified. This fallback driver should act as the primary.

Extending the Component

You can add custom drivers that were not predefined by a driver-based component by calling the extend() method on the manager. This method provides you with a way to register custom driver creators using a Closure. When you request a driver from the manager, it checks if a custom driver creator exists for that driver and calls the custom creator. The Closure registered as the custom creator receives an instance of \Illuminate\Foundation\Application when it’s being called.

protected function callCustomCreator($driver)

{

return $this->customCreators[$driver]($this->app);

}

These custom drivers can override predefined drivers with the same name in the manager if they haven’t already been created.

If you would like to see the complete implementation of the base Manager class, check it out on Github. (Laravel 5.7 as at the time of publishing this article)