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.

39 thoughts on “How to Create a Service Provider in Laravel 5.1

    • Thanks Lux! No plans for an L5 book at the moment, however I will be adding a lot to the Laravel Tips blog, which should cover most of what you need to get up and running.

      Like

  1. Hello Mr. Keck
    Is the last snippert of code in page 2 of this blog wrong? Right after “The new file is located in app/Providers. Go ahead and change it to the following:”

    The braces don’t seem to match (unless you are intending to create a new scope like in c) and there is no initial <?php tag.
    Laravel documentation says that we have to implement a register method in this file.
    Am I missing something?

    If I can get it to work I really like your example, just because you showed how to implement an interface with two different concrete implementations and show us how to easily change one for the other.

    Regards.

    Like

    • Updated and corrected as of 8/18/2015, it was previously chopped apart by wordpress. Also note, I got rid of the pagination for the tutorial, so no more page 2. Thanks for pointing out the typos.

      Like

  2. When using the first concrete implementation I get this error:
    ReflectionException in RouteDependencyResolverTrait.php line 57:

    So in DemoController I added (Don’t know if its correct):
    use App\Helpers\Contracts\RocketShipContract;

    But now I get this error:
    FatalErrorException in RocketShipServiceProvider.php line 30:
    Class ‘App\Providers\RocketShip’ not found

    I’m almost there. Thanks for the tutorial.

    Like

  3. CodeSlayer2010 says:

    I’ve checked out a few of your tutorials and they’ve been great. I wanted to offer a small clarification which could possibly save others some time (I spent about 30 min trying to figure this out).

    So, when I’m following a tutorial I’m usually looking for step by step with pitfalls and expected outcomes explained. In this tutorial, you say:

    “If you have no master page, simply remove that extends line [@extends(‘layouts.master’)] altogether.”

    I did that and all I got when I navigated to /demo was a blank white page staring at me. Google didn’t have the answer, but I figured it out after about 30 min of troubleshooting:

    You also have to remove the @section parts for the page to display “Demo Page” text. A complete newbie (like myself) to Laravel is not going to know that. Perhaps adding a few extra words clarifying this would save others some time of running into a blank white page.

    Keep up the great work on these tutorial,

    Thanks,
    CodeSlayer2010

    Like

  4. Thank you for this tutorial, very helpful.
    I am in doubt about the following (I know it’s up to me to decide, but I am interested in your opinion):
    I have a little five-liner in four of my controller methods that I could easily abstract into (don’t know if that’s the correct terminology) a helper class to keep my code dry.
    This code is about changing a certain session variable depending on a parameter that could be passed to the new class.

    Is it overkill or maybe “wrong” to use a ServiceProvider for this, should I use a simpler Helper function? Does my question make sense ;-)?

    Thanks, Sebastian

    Like

  5. Akkarim says:

    Hello Bill so great your post but i have a problem. I wroten the same of you in my files, just change a folder name from “Contracts” to “Forms”, when write in index function “RocketShipContract $rocketship” that generate this error

    “Argument 1 passed to App\Http\Controllers\PagoTransController::index() must implement interface App\Helpers\Forms\RocketShipContract, instance of App\Helpers\RocketShip given”

    could you help me with this and thanks 😀

    Like

  6. Jorge says:

    Beautiful explanation… The official and extremely confusing Laravel documentation about Service Providers should be overwritten with your article.

    Like

  7. Wayne says:

    Hi

    Great tutoria. I hope you can help me though. I’m battling to run a test on that.

    $rocket = new RocketShip();
    $rocket.blastOff();

    comes back with Error: Call to undefined function blastOff.

    Is there any possibility you can add a unit test to the tutorial or provide any advice. I only use laravel for API’s so have little need for blades and views as per your example.

    Like

    • it should be $rocket->blastOff(), looks like you have a syntax error. Sometimes WordPress chops up the code, these tutorials are kind of old at this point. Hope that helps. I have no plans to write a unit test for this tutorial.

      Like

  8. duc says:

    in DemoController have to load
    use App\Helpers\Contracts\RocketShipContract;
    if don’t have type hint have error class not found

    Like

  9. cnfl says:

    In the code right after “The new file is located in app/Providers. Go ahead and change it to the following:”, shouldn’ it be: use App\Helpers\RocketShip; instead of use App\Helpers\RocketLauncher; ?

    Liked by 1 person

Leave a comment