Service Providers
Every layer has a service provider: it is where the layer plugs itself into the application. The provider extends Lomkit\Osdd\LayerServiceProvider instead of Laravel's ServiceProvider, which adds these methods:
| Method | Use | Guide |
|---|---|---|
loadSeeders() | Register the layer's seeders for osdd:seed and LayersSeeder | Seeders |
overrideConfigFrom() | Override the config of any package with a layer file | Configuration |
withRouting() | Mount the layer's route files | Routes |
withViews(), withTranslations(), withComponents() | Register views, translations and Blade components under the layer name | Views and components |
Laravel's own methods work as usual: loadMigrationsFrom() adds the layer's migrations to php artisan migrate, commands() registers its Artisan commands. Every signature is in the API reference.
osdd:layer generates this provider with the provider generator:
<?php
namespace Functional\Orders\Providers;
use Lomkit\Osdd\LayerServiceProvider;
class OrdersServiceProvider extends LayerServiceProvider
{
public function boot(): void
{
if ($this->app->runningInConsole()) {
$this->loadMigrationsFrom(__DIR__ . '/../../database/migrations');
}
$this->withRouting(
web: __DIR__ . '/../../routes/web.php',
api: __DIR__ . '/../../routes/api.php',
commands: __DIR__ . '/../../routes/console.php',
channels: __DIR__ . '/../../routes/channels.php',
);
$this->withViews(__DIR__ . '/../../resources/views');
$this->withTranslations(__DIR__ . '/../../lang');
}
public function register(): void
{
//
}
}
Missing route files, views and lang folders are skipped, so every call is safe in a fresh layer. The generated provider registers no seeder: the seeder generator, or osdd:seeder, adds the loadSeeders() call.
Registering the provider
Laravel boots the provider because the layer's composer.json lists it:
"extra": {
"laravel": {
"providers": [
"Functional\\Orders\\Providers\\OrdersServiceProvider"
]
}
}
osdd:layer and osdd:provider add this entry for you. Run composer update functional/orders once after adding a provider so Laravel rebuilds its package manifest. Do not list layer providers in bootstrap/providers.php.
Generators keep it in sync
Several generators add the line their file needs to the layer provider, so the new file is loaded without editing anything:
| Command | Adds to the provider |
|---|---|
osdd:migration, osdd:*-table | $this->loadMigrationsFrom(...) in boot() |
osdd:seeder | $this->loadSeeders([...]) in boot() |
osdd:config | $this->overrideConfigFrom(...) in register() |
osdd:command | $this->commands([...]) in boot() |
osdd:view | $this->withViews(...) in boot() |
osdd:component | $this->withViews(...) and $this->withComponents(...) in boot() |
A call the provider already makes is never added twice, whatever its layout. When the layer has no provider, or the method is missing, the generator prints the line to add by hand. See Generators.
Policies
Laravel discovers a policy that sits in the Policies namespace of its model's layer, the same way it does for app/:
| Model | Policy found |
|---|---|
Functional\Orders\Models\Order | Functional\Orders\Policies\OrderPolicy |
Functional\Users\Models\User | Functional\Users\Policies\UserPolicy |
osdd:policy OrderPolicy --model=Order --layer=functional/orders creates the policy in that namespace, so there is nothing to register. Call Gate::policy() only for a policy whose name or namespace does not follow the convention:
use Illuminate\Support\Facades\Gate;
public function boot(): void
{
Gate::policy(Order::class, OrderAccessPolicy::class);
}
Commands, observers and events
Anything a Laravel service provider does works in a layer provider. Observers are never discovered: register them here.
public function boot(): void
{
Order::observe(OrderObserver::class);
Event::listen(OrderPlaced::class, SendOrderConfirmation::class);
$this->commands([PruneAbandonedOrders::class]);
}
osdd:command adds the commands() call for you. With osdd.events.discover on, the listeners of the layer's src/Listeners are registered without Event::listen(): see Events.
composer.json does not show.Two providers named OsddServiceProvider
An OSDD project has two classes with that short name:
| Class | Belongs to | Does |
|---|---|---|
Lomkit\Osdd\OsddServiceProvider | The package, in vendor/ | Registers the osdd:* commands, the layer discovery and its cache, the about section, event discovery, the Tinker and IDE Helper support |
Technical\Osdd\Providers\OsddServiceProvider | Your application, created by osdd:start | A layer provider like any other: loads technical/osdd/config/osdd.php, the skeleton migrations, and binds LayersSeeder as the default seeder |