Layer Service Provider
Every layer should have a service provider that extends Xefi\LaravelOSDD\LayerServiceProvider instead of Laravel's base Illuminate\Support\ServiceProvider.
<?php
namespace Functional\Orders\Providers;
use Xefi\LaravelOSDD\LayerServiceProvider;
use Functional\Orders\Database\Seeders\OrdersSeeder;
class OrdersServiceProvider extends LayerServiceProvider
{
public function boot(): void
{
$this->loadMigrationsFrom(__DIR__ . '/../../database/migrations');
$this->loadSeeders([OrdersSeeder::class]);
$this->overrideConfigFrom(__DIR__ . '/../../config/orders.php', 'orders');
}
}
Methods
loadMigrationsFrom()
Inherited from Laravel's base ServiceProvider. Registers the layer's migration directory so php artisan migrate picks up the layer's migrations.
$this->loadMigrationsFrom(__DIR__ . '/../../database/migrations');
loadSeeders(array $seeders, int $priority = 0): void
Pushes one or more seeder class-strings into the global SeederRegistry singleton. Registered seeders are discovered by php artisan osdd:seed. The optional $priority parameter controls execution order — lower numbers run first (default: 0).
// Default priority
$this->loadSeeders([
OrdersSeeder::class,
OrderStatusSeeder::class,
]);
// Run this layer's seeders before others (e.g. foundational reference data)
$this->loadSeeders([RolesSeeder::class], priority: -10);
loadSeeders is the OSDD equivalent of adding seeders to DatabaseSeeder::call(). The difference is that each layer manages its own seeders — no central file to edit.overrideConfigFrom(string $path, string $key): void
Deep-merges the config file at $path over the already-loaded config key $key after the application boots. Layer values win over whatever was loaded first.
$this->overrideConfigFrom(__DIR__ . '/../../config/orders.php', 'orders');
Why this matters: Laravel's built-in mergeConfigFrom() gives the already-loaded config priority — layer values are ignored if the key already exists. overrideConfigFrom() runs after app()->booted() using array_replace_recursive, so the layer's values always take precedence.
| Method | Who wins |
|---|---|
mergeConfigFrom() | Existing config wins |
overrideConfigFrom() | Layer config wins |
Full Example
<?php
namespace Functional\Orders\Providers;
use Xefi\LaravelOSDD\LayerServiceProvider;
use Functional\Orders\Database\Seeders\OrdersSeeder;
use Functional\Orders\Database\Seeders\OrderStatusSeeder;
use Functional\Orders\Contracts\PaymentGatewayInterface;
use Functional\Orders\Gateways\StripePaymentGateway;
class OrdersServiceProvider extends LayerServiceProvider
{
public function register(): void
{
$this->app->bind(
PaymentGatewayInterface::class,
StripePaymentGateway::class
);
}
public function boot(): void
{
// Load this layer's migrations
$this->loadMigrationsFrom(__DIR__ . '/../../database/migrations');
// Register seeders with the global registry
$this->loadSeeders([
OrdersSeeder::class,
OrderStatusSeeder::class,
]);
// Override the 'orders' config key with this layer's config file
$this->overrideConfigFrom(__DIR__ . '/../../config/orders.php', 'orders');
// Standard Laravel service provider features work too
$this->loadRoutesFrom(__DIR__ . '/../../routes/api.php');
}
}
Tinker Short-Name Aliases
When running inside Laravel Tinker, OSDD automatically registers an SPL autoloader that resolves layer classes by their short name (without the full namespace). This means you can type Invoice instead of Functional\Billing\Models\Invoice directly in the Tinker REPL.
# Instead of:
>>> Functional\Orders\Models\Order::first()
# You can write:
>>> Order::first()
This alias resolution is only active inside Tinker — it has no effect in normal application code. The autoloader scans all configured layer directories at boot time using the class map built by LaravelOSDDServiceProvider.
Functional\Users\Models\User and Functional\Admin\Models\User), the first one registered wins. Use fully-qualified names in Tinker to disambiguate.Auto-discovery
For the service provider to be booted automatically by Laravel, it must be listed in the layer's composer.json:
{
"extra": {
"laravel": {
"providers": [
"Functional\\Orders\\Providers\\OrdersServiceProvider"
]
}
}
}
osdd:layer injects this entry automatically when the service-provider generator is selected. After running composer update functional/orders, Laravel discovers and boots the provider without any changes to bootstrap/providers.php.