Back to Course |
Design Patterns in Laravel 11

Factory and FactoryContract

Another pattern found extensively in Laravel is the Factory pattern:

use Illuminate\Contracts\Auth\Factory as FactoryContract;
 
class AuthManager implements FactoryContract
{
// ...
}
use Illuminate\Contracts\Mail\Factory as FactoryContract;
 
class MailManager implements FactoryContract
{
// ...
}
use Illuminate\Contracts\Cache\Factory as FactoryContract;
 
class CacheManager implements FactoryContract
{
// ...
}

As you can see, all of these Managers implement the FactoryContract interface (or Factory, as it uses an alias to rename it to FactoryContract).

But what is the Factory pattern?


Factory Pattern

The pattern itself is simple - it is meant for object creation and extendability. This means we define an Interface or an Abstract class that describes how the object should be created. But what does that actually mean?

Let's take a rough example:

interface FactoryContract
{
public function getForm(array $details);
public function submitForm(array $request);
}

Once we have this interface, we can create a class that implements it:

class PasswordLogin implements FactoryContract
{
public function getForm(array $details)
{
// Retrieve the Form information
}
 
public function submitForm(array $request)
{
// Post the form
}
}

Of course, it does not make sense if we are using this for a single class. But as soon as we add more classes, we can use the same interface to create them:

class SocialLogin implements FactoryContract
{
public function getForm(array $details)
{
// Retrieve the Form information
}
 
public function submitForm(array $request)
{
// Post the form
}
}

Now, when we call the class - we don't care which one we use as they both implement the same interface.

This allows us to remove the "guessing" part of the code and make it compatible regardless of which class we are using.


Auth Manager - Factory

Now let's look at the Auth Manager in Laravel:

Illuminate/Auth/AuthManager.php

use Illuminate\Contracts\Auth\Factory as FactoryContract;
 
class AuthManager implements FactoryContract
{
// ...
}

This class is creating an Auth Manager that will always have the following methods:

interface Factory
{
/**
* Get a guard instance by name.
*
* @param string|null $name
* @return \Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard
*/
public function guard($name = null);
 
/**
* Set the default guard the factory should serve.
*
* @param string $name
* @return void
*/
public function shouldUse($name);
}

This means that we can always use the same methods no matter which manager we use.

In the case of Laravel, the framework creates a Singleton with the manager:

$this->app->singleton('auth', fn ($app) => new AuthManager($app));

Which can be overridden by the user:

app/Providers/AppServiceProvider.php

public function register(): void
{
$this->app->singleton('auth', fn ($app) => new CustomAuthManager($app));
}

If we make a new class that implements the same interface, we can use it instead of the default one, and it will work without any issues:

Illuminate/Contracts/Auth/Factory.php

use Illuminate\Contracts\Auth\Factory as FactoryContract;
 
class CustomAuthManager implements FactoryContract
{
public function guard($name = null)
{
// ...
}
 
public function shouldUse($name)
{
// ...
}
}

This allowed us to replace the default Auth Manager directly with our own without changing any code that uses it.


Mail Manager - Factory

The same goes with the Mail Manager:

Illuminate/Mail/MailManager.php

use Illuminate\Contracts\Mail\Factory as FactoryContract;
 
class MailManager implements FactoryContract
{
// ...
}

The factory itself is really simple:

Illuminate/Contracts/Mail/Factory.php

interface Factory
{
/**
* Get a mailer instance by name.
*
* @param string|null $name
* @return \Illuminate\Contracts\Mail\Mailer
*/
public function mailer($name = null);
}

Once again, this is a Singleton that can be overridden by the user when creating custom mailers.


Cache Manager - Factory

Last of our examples is the Cache Manager:

Illuminate/Cache/CacheManager.php

use Illuminate\Contracts\Cache\Factory as FactoryContract;
 
class CacheManager implements FactoryContract
{
// ...
}

The factory used here is, once again, a really simple one:

Illuminate/Contracts/Cache/Factory.php

interface Factory
{
/**
* Get a cache store instance by name.
*
* @param string|null $name
* @return \Illuminate\Contracts\Cache\Repository
*/
public function store($name = null);
}

This implements some method signatures that we can use to create our own cache stores.


In general, Laravel uses the Factory pattern to give us direction on how to create our own classes that can be used instead of the default ones.

The end goal is to create things consistently. This way, you can easily switch between different classes without changing the code that uses them.