Service Providers

Introduction

Service providers are the central class of all addon registering. Service providers let you define views, overrides, routes, commands, schedules, and more.

This documentation assumes you already have an understanding of Laravel service providers.

Defining Service Providers

Service providers are usually created for you when using make:addon. Even your theme, which every project will likely have, is generated with a service provider.

If you would like to make your own you can do so by creating a class that extends Anomaly\Streams\Platform\Addon\AddonServiceProvider.

If your addon is ExampleModule your service provider should be called ExampleModuleServiceProvider to be detected automatically.

Service providers for installable addons will be ignored unless they are both installed and enabled.

<?php namespace Anomaly\ExampleModule;

use Anomaly\Streams\Platform\Addon\AddonServiceProvider;
use Illuminate\Routing\Router;

class ExampleModuleServiceProvider extends AddonServiceProvider
{

    /**
     * Additional addon plugins.
     *
     * @type array|null
     */
    protected $plugins = [];

    /**
     * The addon Artisan commands.
     *
     * @type array|null
     */
    protected $commands = [];

    /**
     * The addon's scheduled commands.
     *
     * @type array|null
     */
    protected $schedules = [];

    /**
     * The addon API routes.
     *
     * @type array|null
     */
    protected $api = [];

    /**
     * The addon routes.
     *
     * @type array|null
     */
    protected $routes = [];

    /**
     * The addon middleware.
     *
     * @type array|null
     */
    protected $middleware = [
        //Anomaly\ExampleModule\Http\Middleware\ExampleMiddleware::class
    ];

    /**
     * Addon group middleware.
     *
     * @var array
     */
    protected $groupMiddleware = [
        //'web' => [
        //    Anomaly\ExampleModule\Http\Middleware\ExampleMiddleware::class,
        //],
    ];

    /**
     * Addon route middleware.
     *
     * @type array|null
     */
    protected $routeMiddleware = [];

    /**
     * The addon event listeners.
     *
     * @type array|null
     */
    protected $listeners = [
        //Anomaly\ExampleModule\Event\ExampleEvent::class => [
        //    Anomaly\ExampleModule\Listener\ExampleListener::class,
        //],
    ];

    /**
     * The addon alias bindings.
     *
     * @type array|null
     */
    protected $aliases = [
        //'Example' => Anomaly\ExampleModule\Example::class
    ];

    /**
     * The addon class bindings.
     *
     * @type array|null
     */
    protected $bindings = [];

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

    /**
     * Additional service providers.
     *
     * @type array|null
     */
    protected $providers = [
        //\ExamplePackage\Provider\ExampleProvider::class
    ];

    /**
     * The addon view overrides.
     *
     * @type array|null
     */
    protected $overrides = [
        //'streams::errors/404' => 'module::errors/404',
        //'streams::errors/500' => 'module::errors/500',
    ];

    /**
     * The addon mobile-only view overrides.
     *
     * @type array|null
     */
    protected $mobile = [
        //'streams::errors/404' => 'module::mobile/errors/404',
        //'streams::errors/500' => 'module::mobile/errors/500',
    ];

    /**
     * Register the addon.
     */
    public function register()
    {
        // Run extra pre-boot registration logic here.
        // Use method injection or commands to bring in services.
    }

    /**
     * Boot the addon.
     */
    public function boot()
    {
        // Run extra post-boot registration logic here.
        // Use method injection or commands to bring in services.
    }

    /**
     * Map additional addon routes.
     *
     * @param Router $router
     */
    public function map(Router $router)
    {
        // Register dynamic routes here for example.
        // Use method injection or commands to bring in services.
    }

}

Definitions

Plugins

Use the $plugins property to define plugins. This is helpful when developing a module that requires it's own plugin.

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

Artisan Commands

Use the $commands property to define Artisan commands provided by the addon.

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

Scheduled Tasks

Use the $schedules property to define scheduled tasks.

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,
    ],
];

Routes

Use the routes property to define addon routes. Routes defined here are very similar to the arguments you would typically pass Laravel's router:

protected $routes = [
    'login' => 'Anomaly\UsersModule\Http\Controller\[email protected]',
];

Middleware

Use the $middleware property to define middleware to push into the MiddlewareCollection. Middleware in this collection are ran for every request:

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

Event Listeners

use the $listeners property to define event listeners.

protected $listeners = [

    // ...

    'Anomaly\UsersModule\User\Event\UserWasLoggedIn' => [
        'Anomaly\UsersModule\User\Listener\TouchLastLogin',
    ],
];

You can also dictate the listener's priority by specifying as listener => priority. Listeners are ran in order of highest to lowest priority.

protected $listeners = [

    // ...

    'Anomaly\Streams\Platform\Application\Event\ApplicationHasLoaded' => [
        'Anomaly\UsersModule\User\Listener\TouchLastActivity' => -100,
    ],
];

Aliases

Use the $aliases property to define aliases with the service container.

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

Bindings

Use the $bindings property to define bindings with the service container.

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

Singletons

Use the $singletons property to define singleton bindings with the service container..

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

Service Providers

Sometimes you might ship your addon with a package dependency that requires a service provider. Use the $providers property to register other service providers.

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

View Overrides

Use the $overrides property to specify view => override definitions to use should the addon be relative to the current request.

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

Mobile View Overrides

Use the $overrides property to specify mobile-only view => override definitions to use should the addon be relative to the current request.

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

Request Lifecycle

Register

The register method is ran very early in addon registration. You should only bind things into the service container. Typically, you should never attempt to use any class or functionality from another addon within the register method. Otherwise, you may accidentally use something that is provided but has not been registered yet itself.

Register is ran after the above definitions have been registered so you may use those at will.

<?php

namespace Anomaly\ExampleModule;

use Riak\Connection;
use Anomaly\Streams\Platform\Addon\AddonServiceProvider;

class ExampleModuleServiceProvider extends AddonServiceProvider
{

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

Boot

The boot method is called after all other addon service providers have been registered. It is now safe to use functionality from other addons.

<?php

namespace Anomaly\ExampleModule;

use Anomaly\Streams\Platform\Addon\AddonServiceProvider;

class ExampleModuleServiceProvider extends AddonServiceProvider
{

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        if (auth()->user()) {
            // Register a little something extra special.
        }
    }
}

Map

The map method is called last and gives you an opportunity to do some routing based on logic from another addon perhaps.

<?php

namespace Anomaly\ExampleModule;

use Illuminate\Routing\Router;
use Anomaly\Streams\Platform\Addon\AddonServiceProvider;

class ExampleModuleServiceProvider extends AddonServiceProvider
{

    /**
     * Map any additional services.
     *
     * @return void
     */
    public function map(Router $router)
    {
        $router->($path, $route);
    }
}