Don't repeat yourself, use the Laravel service container!

Roughly a 3 minute read by Chris Willerton

Undoubtedly one of Laravel’s best features is the service container. It’s a powerful tool for resolving class dependencies and managing dependency injection. Let’s run through how you can bind something to the container and pull it out in a pre-configured state later in your application.

Imagine you have a class that manages your integration to a third party service, something like a helper class for Stripe. This is the class that manages all the API calls and logic for integration with the service.

In ‘native PHP’ if you wanted to use a class like this then you might have to instantiate a new object every time you want to use it. This might involve passing in dependencies, an API key, or some other config type item, as is the case with the example below.

$api_key = config(‘services.stripe.api_key’);
$stripe_helper = new App\Helpers\Stripe($api_key);

Wouldn’t it be nice to not have to do this every time you want to use the class? Imagine taking away the repetition of writing this block of code along with the potential to introduce new bugs every time you write it...

With this in mind, let’s ‘bind’ how this class is resolved into the service container and then let the container resolve it for us each time we want to use it. Adding the below into the register method of your AppServiceProvider will tell Laravel that each time the application tries to instantiate this class, we actually want it to be instantiated in this specific way.

$this->app->bind(‘App\Helpers\Stripe’, function($app)
{
    $api_key = config(‘services.stripe.api_key’);
    return new \App\Helpers\Stripe($api_key);
});

Now when we want our Stripe class instantiated we can just use the global app helper like below.

app(‘App\Helpers\Stripe’);

Each time we make the object like this, we’re guaranteed to get it the exact same way. This also includes any time this class is automatically resolved by Laravel (such as in a controller method).

public function getIndex(\App\Helpers\Stripe $stripe)
{
    $stripe->getCustomer();
}

Pretty cool right?

Depending on your use case you can also bind classes into the container as a singleton. Just replace your reference to `bind` with `singleton`.

$this->app->singleton(‘App\Helpers\Stripe’...

Be careful about binding as a singleton though. You might accidentally find yourself in a debate about anti-patterns, testing, and tight coupling. I’ll let you travel this contentious path on your own though!

In short, the Laravel service container is a very powerful tool, one that you would be wise to learn a lot about. What we've looked at in this post is a relatively simple use case; the service container also has other powerful features that allow you to create some excellent solutions to tricky problems. See the Laravel docs for more information.