One of the keys to building a well architected Laravel application is learning to use service providers as an organizational tool. When you are registering many classes with the IoC container, all of those bindings can start to clutter your ``app/start`` files. Instead of doing container registerations in those files, create service providers that register related services.
> ### **Get It Started** ###
>
> Your application's "start" files are all stored in the ``app/start`` directory. These are "bootstrap" files that are loaded based on the type of the request entering your application. Start files named after an environment are loaded after the global ``start.php`` file. Finally, the artisan.php ``start file`` is loaded when any console command is executed.
>
>
Let's explore an example. Perhaps our application is using [Pusher](http://pusher.com/) to push messages to clients via WebSockets. In order to decouple ourselves from Pusher, it will be benificial to create an ``EventPusherInterface``, and a ``PusherEventPusher`` implementation. This will allow us to easily change WebSocket providers down the road as requirements change or our application grows.
~~~
<!-- lang: php -->
interface EventPusherInterface{
public function push($message, array $data = array());
}
class PusherEventPusher implements EventPusherInterface{
public function __construct(PusherSdk $pusher)
{
$this->pusher = $pusher;
}
public function push($message, array $data = array())
{
// Push message via the Pusher SDK...
}
}
~~~
Next, let's create an ``EventPusherServiceProvider``:
~~~
<!-- lang:php -->
use Illuminate\Support\ServiceProvider;
class EventPusherServiceProvider extends ServiceProvider {
public function register()
{
$this->app->singleton('PusherSdk', function()
{
return new PusherSdk('app-key', 'secret-key');
}
$this->app->singleton('EventPusherInterface', 'PusherEventPusher');
}
}
~~~
Great! Now we have a clean abstraction over event pushing, as well as a convenient place to register this, and other related bindings, in the container. Finally, we just need to add the ``EventPusherServiceProvider`` to our providers array in the ``app/config/app.php`` configuration file. Now we are ready to inject the ``EventPusherInterface`` into any controller or class within our application.
> ### **Should You Singleton?** ###
>
> You will need to evaluate whether to bind classes with bind or singleton. If you only want one instance of the class to be created per request cycle, use singleton. Otherwise, use bind.
>
Note that a service provider has an ``$app`` instance available via the base ``ServiceProvider`` class. This is a full ``Illuminate\Foundation\Application`` instance, which inherits from the ``Container`` class, so we can call all of the IoC container methods we are used to. If you preffer to use the ``App`` facade inside the service provider, you may do that as well:
~~~
App::singleton('EventPusherInterface', 'PusherEventPusher');
~~~
Of course, service providers are not limited to registering certain kinds of services. We could use them to register our cloud file storage services, database access services, a custom view engine such as Twig, etc. They are simply bootstrapping and organizational tools for your application. Nothing more.
So, don't be scared to create your own service providers. They are not something that should be strictly limited to distributed packages, but rather are great organizational tools for your own applications. Be creative and use them to bootstrap your various application components.
- Dependency Injection
- The Problem
- Build A Contract
- Take It further
- Too Much Java?
- The IoC Container
- Basic Binding
- Reflective Resolution
- Interface As Contract
- Strong Typing & Water Fowl
- A Contract Example
- Interface & Team Development
- Service Provider
- As Bootstrapper
- As Organizer
- Booting Providers
- Providing The Core
- Application Structure
- MVC Is Killing You
- Bye, Bye Models
- It's All About The Layers
- Where To Put "Stuff"
- Applied Architecture: Decoupling Handles
- Decoupling Handlers
- Other Handlers
- Extending The Framework
- Manager & Factories
- Cache
- Session
- Authentication
- IoC Based Extension
- Request Extension
- Single Responsibility Principle
- Open Closed Principle