How to Create a Service Provider in Laravel 5.1

Access all tutorials in sprocket icon.

June 11, 2015 from author Bill Keck.

A beginner-friendly tutorial on building a service provider in Laravel 5.1.

I mentioned in my last blog that I love the Laravel 5.1 architecture, especially when it comes to service providers, which are the building blocks of your application. Configuration of an application can often be tricky task, depending on the framework you are using, but lucky for us, this is a fairly simple task in Laravel.

So let’s start by creating a route that we’ll use for demonstration purposes. Go to app/Http/routes.php and add the following route:



Route::resource('demo', 'DemoController');

Since we’re using Route::resource, we get index, show, create, edit, update, store, and destroy routes defined for us.

Now in perfect symmetry, we can use our artisan command line tool to create a matching controller for us. Type the following:



php artisan make:controller DemoController

Let’s open that file and change the index method to the following:



public function index()
{

    return view('demo.index');
}

Now let’s make a folder for the view in app/Resources/views named Demo, and in that folder create a view named index.blade.php like so:



@extends('layouts.master')

@section('content')
<h1>Demo Page</h1>
@endsection

In this case we are pulling in our master page, which I have in the layouts folder, master.blade.php. If you have a master page with another name, use that instead. If you have no master page, simply remove that extends line altogether, along with the @section statements.

Assuming you have set up your development environment to resolve your domain, when you hit the route yourapplication.com/demo, you should see the words Demo Page.

Ok, so now let’s create a service provider. This service provider isn’t going to do anything particularly useful. It’s just going to show you how to set one up.

Let’s start by creating a Helpers folder in our app directory. Then inside the Helpers folder, create a Contracts folder. Inside the Contracts folder, create RocketShipContract.php with the following contents:



<?php

namespace App\Helpers\Contracts;

Interface RocketShipContract
{

    public function blastOff();


}

As you probably are aware, an interface is a contract that enforces architecture. In order for a class to implement the interface, it must contain a public function named blastOff.

So why bother making a contract? Well, one of the amazing features in Laravel is that you can type hint the contract, and the service provider will return an instance of whatever concrete class you have bound to it. This creates an incredibly flexible and loosely coupled structure because you will be able to easily swap out implementations with a single line of code. We will see how this works in a little while.

First, let’s create the concrete class. In the app/Helpers folder, create RocketShip.php with the following:



<?php

namespace app\Helpers;

use App\Helpers\Contracts\RocketShipContract;

class RocketShip implements RocketShipContract
{

    public function blastOff()
    {

        return 'Houston, we have ignition';

    }

}

You can see our concrete class doesn’t do much, but we are mainly interested in how all this stitches together. You can decide for yourself what services you want to provide to your application.

Ok, now we need to create the service provider, which will bind the contract and the concrete class. Go to your command line and type the following:



php artisan make:provider RocketShipServiceProvider

Hit enter and it will create the class for you.

The new file is located in app/Providers. Go ahead and change it to the following:



<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Helpers\RocketLauncher;

class RocketShipServiceProvider extends ServiceProvider
{
    protected $defer = true;

    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind('App\Helpers\Contracts\RocketShipContract', function(){

            return new RocketShip();

        });
    }

    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return ['App\Helpers\Contracts\RocketShipContract'];
    }

}

So let’s look at the pieces:



<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Helpers\RocketShip;

class RocketShipServiceProvider extends ServiceProvider
{

All fairly straightforward. We have our namespace, use statements and class declaration. When you create service providers, you will have to import the concrete class, in this case RocketShip, as I did with the use statement.

Next we have:



    protected $defer = true;

Setting the $defer property to true means this class will only be loaded when necessary, so the application runs more efficiently.

Next we have the boot function, which is just an empty stub, since we are not configuring anything.

Following that, we have the register method:



/**
 * Register the application services.
 *
 * @return void
 */
public function register()
{
    $this->app->bind('App\Helpers\Contracts\RocketShipContract', function(){

        return new RocketShip();

    });
}

You can see we are using the bind method to bind the contract to the concrete class. This is the one place within the service provider where the concrete method is defined. So if you wanted to change which the class the binding will call, it’s quick and easy. We will see this in action later.

Finally, we have the provides method:



/**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return ['App\Helpers\Contracts\RocketShipContract'];
    }

}

You need the above method if you are setting the $defer property to true.

All in all, this is a really simple class, which is part of the beauty of all this.

Ok, next we need to tell our application to look for this class, and we do that by adding it to the providers array in config/app.php.



        /*
         * Application Service Providers...
         */

        App\Providers\AppServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,
        App\Providers\RocketShipServiceProvider::class,

I included some of the other providers for reference, you can see our provider on the last line. Once you save this, you should be good to go.

So let’s go to our DemoController index action and modify it to the following:



public function index(RocketShipContract $rocketship)
{
        $boom = $rocketship->blastOff();

        return view('demo.index', compact('boom'));
}

So in this case, we are type hinting RocketShipContract and giving it an instance variable $rocketship. Laravel knows through the service provider that you actually want the RocketShip class because we bound it to the contract in the service provider. How cool is that?

Then we are simply calling the blastOff method and assigning it to a variable, which we will pass onto the view. Let’s modify the view:



@extends('layouts.master')


@section('content')

    {{ $boom }}

@endsection

You can see I’m using blade to echo the variable. So in your browser, you should see:



Houston, we have ignition.

So now to demonstrate ease at which you can swap out implementations, let’s create a second concrete class in our Helpers folder. Let’s call it RocketLauncher.php and place the following within it:



<?php

namespace app\Helpers;

use App\Helpers\Contracts\RocketShipContract;

class RocketLauncher implements RocketShipContract
{

    public function blastOff()
    {

        return 'Houston, we have launched!';

    }

}

You can see this is a lot like our RocketShip class, but our blastOff method is slightly different. So now to implement this, we simply change one line in our service provider in the register method:



public function register()
    {
        $this->app->bind('App\Helpers\Contracts\RocketShipContract', function(){

            return new RocketLauncher();

        });
    }


And also the use statement:



use App\Helpers\RocketLauncher;

And with those simple changes, we now have a different implementation bound to the contract and of course a new result in the browser.

Even though we did a super trivial example for this tutorial, you can see the benefits of this architecture. By coding to a contract instead of a concrete class, we gave ourselves flexibility and an easier way to maintain the code.

A couple of gotchas to look out for. You can’t rename the service provider without deleting and creating a new one from artisan because something behind the scenes causes the class not to be seen. It’s probably related to autoload. You can try running composer dump-autoload from the command line if you run into this type of situation. If that doesn’t work, delete the file and start over.

The other thing is don’t add the service provider to the config/app.php file until the last step. Having a class that doesn’t exist in there will mess up artisan.

The laravel framework has excellent documentation and you can read more about laravel service providers there.

I hope you have enjoyed this tutorial and found it useful. Click on the sprocket icon at the top of the page to see all tutorials. Please comment, share, and like if you can, thanks!

I don’t have a donate button, but If you would like to support my work and learn more about Laravel, you can do so by buying one of my books, Laraboot: laravel 5* For Beginners, I really appreciate it.

Advertisements