Service Providers

Service providers are the central place of all PyroCMS addon bootstrapping. Your own custom website or application, the Streams Platform, all addons, and all of Laravel's core services are bootstrapped via service providers.

But, what do we mean by "bootstrapped"? In general, we mean registering things, including registering service container bindings, event listeners, middleware, and even routes. Service providers are the central place to configure your application and addons.

PyroCMS uses primarily addon service providers to register things because Pyro has a modular addon-based infrastructure. However you can still use Laravel service providers all the same.

In this section you will learn how to write your own addon service providers and register various services with them.

Writing Service Providers

All addon service providers extend the Anomaly\Streams\Platform\Addon\AddonServiceProvider class. Addon service providers contain a number of properties to quickly define bindings, routes, and even views. They also contain the Laravel register and a boot methods.

**Note:** The **register** and **boot** method are both called with the service container and support method injection.

When creating an addon the service provider will automatically be created for you:

php artisan make:addon example.module.test

You can also create your own addon service providers by transforming the addon class name into it's corresponding service provider class name:

TestModule -> TestModuleServiceProvider

Here is what a generated addon service provider looks like:

<?php namespace Example\TestModule;

use Anomaly\Streams\Platform\Addon\AddonServiceProvider;

class TestModuleServiceProvider extends AddonServiceProvider
{

    /**
     * The addon plugins.
     *
     * @var array
     */
    protected $plugins = [];

    /**
     * The addon routes.
     *
     * @var array
     */    
    protected $routes = [];

    /**
     * The addon middleware.
     *
     * @var array
     */
    protected $middleware = [];

    /**
     * The addon event listeners.
     *
     * @var array
     */
    protected $listeners = [];

    /**
     * The addon alias bindings.
     *
     * @var array
     */
    protected $aliases = [];

    /**
     * The addon simple bindings.
     *
     * @var array
     */
    protected $bindings = [];

    /**
     * Other addon service providers.
     *
     * @var array
     */
    protected $providers = [];

    /**
     * The addon singleton bindings.
     *
     * @var array
     */
    protected $singletons = [];

    /**
     * The addon view overrides.
     *
     * @var array
     */
    protected $overrides = [];

    /**
     * The addon mobile-only view overrides.
     *
     * @var array
     */
    protected $mobile = [];

    /**
     * Register the addon.
     *
     * @var void
     */
    public function register()
    {
    }

    /**
     * Boot the addon.
     *
     * @var void
     */
    public function map()
    {
    }
}
AddonServiceProvider::$plugins

The $plugins property let's you easily define plugins provided by the addon. This is helpful if you develop a module that has specific plugin functions to accomodate it's use.

Example

protected $plugins = [
    \Anomaly\UsersModule\UsersModulePlugin::class,
];
AddonServiceProvider::$commands

The $commands property let's you easily define Artisan commands provided by the addon.

Example

protected $commands = [
    \Anomaly\ExampleModule\Console\DoWork::class,
];
AddonServiceProvider::$schedules

The $schedules property let's you easily define scheduled tasks.

Example

protected $schedules = [
    'daily' => [
        \Anomaly\LogsModule\Console\ArchiveLogs::class,
    ],
    'dailyAt|11:00' => [ // dailyAt('13:00')
      \Anomaly\LogsModule\Console\ArchiveLogs::class,
    ],
    'twiceDaily|1, 13' => [ // twiceDaily(1, 13)
      \Anomaly\LogsModule\Console\ArchiveLogs::class,
    ],
    '*/10 * * * *' => [
        \Anomaly\LogsModule\Console\ScrapeLogs::class,
    ],
];
AddonServiceProvider::$routes

The routes property let's you quickly define basic addon routes. Routes defined here are very similar to the arguments you would typically pass Laravel's Router class:

**Learn More:** For more information on route definitions checkout the [documentation on routing](#the-basics/routing).

Example

protected $routes = [
    'login' => 'Anomaly\UsersModule\Http\Controller\LoginController@login',
];
AddonServiceProvider::$middleware

The $middleware property let's you define middleware to push into the MiddlewareCollection. Middleware in this collection are ran for every request:

Example

protected $middleware = [
    \Anomaly\UsersModule\Http\Middleware\CheckSecurity::class
];
AddonServiceProvider::$listeners

The $listeners property let's you easily define event listeners. Event listeners are defined in an Event => (array)Listeners format.

**Pro Tip:** You can also dictate the listener's priority by including a priority value. Listeners are ran in order of highest to lowest priority.

Example

protected $listeners = [
    'Anomaly\UsersModule\User\Event\UserWasLoggedIn'                  => [
        'Anomaly\UsersModule\User\Listener\TouchLastLogin',
    ],
    'Anomaly\Streams\Platform\Application\Event\ApplicationHasLoaded' => [
        'Anomaly\UsersModule\User\Listener\TouchLastActivity' => -100,
    ],
];
AddonServiceProvider::$aliases

The $aliases property lets you quickly define alias bindings.

Example

protected $aliases = [
    'users' => \Anomaly\UsersModule\User\Contract\UserRepositoryInterface::class
];
AddonServiceProvider::$bindings

The $bindings property lets you quickly define simple bindings.

Example

protected $bindings = [
    'login' => 'Anomaly\UsersModule\User\Login\LoginFormBuilder',
];
AddonServiceProvider::$providers

Sometimes you might ship another package dependency with your addon. Or split up registration tasks between multiple service providers. The $providers property let's you do this.

Example

protected $providers = [
    \TeamTNT\Scout\TNTSearchScoutServiceProvider::class
];
AddonServiceProvider::$singletons

The $singletons let's you easily define singleton bindings.

Example

protected $singletons = [
    'Anomaly\UsersModule\User\Contract\UserRepositoryInterface' => 'Anomaly\UsersModule\User\UserRepository',
];
AddonServiceProvider::$overrides

The $overrides property allows you to define specific view override definitions for the view composer.

Example

protected $overrides = [
    'streams::form/partials/wrapper' => 'example.theme.test::overrides/field_wrapper',
];
AddonServiceProvider::$mobile

The $mobile property allows you to define specific mobile-only view override definitions for the view composer.

Example

protected $mobile = [
    'streams::form/partials/wrapper' => 'example.theme.test::mobile/field_wrapper',
];
AddonServiceProvider::register()

As mentioned previously, within the register method, you should only bind things into the service container. Typically, you should never attempt to register any event listeners, routes, or any other piece of functionality within the register method. Otherwise, you may accidentally use a service that is provided by a service provider which has not loaded yet.

In PyroCMS however there is a predictable loading order within the addon itself so you may inject any bindings defined in the properties for use. They have already been registered.

Let's take a look at a basic service provider. Within any of your service provider methods, you always have access to the $app property which provides access to the service container:

Returns: void or null
Example
<?php

namespace App\Providers;

use Riak\Connection;
use Illuminate\Support\ServiceProvider;

class RiakServiceProvider extends ServiceProvider
{
    /**
     * Register bindings in the container.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(Connection::class, function ($app) {
            return new Connection(config('riak'));
        });
    }
}
AddonServiceProvider::boot()

So, what if we need to register a view composer within our service provider? This should be done within the boot method. This method is called after all other addon service providers have been registered, meaning you have access to all other services that have been registered by all other addons.

Returns: void
Example
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class ComposerServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        view()->composer('view', function () {
            //
        });
    }
}