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.
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:
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.
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 () {
//
});
}
}