v1 → v2
v2 introduces layer-scoped routing via withRouting(), runs config overrides during register() (instead of after app->booted()), keeps the App\ PSR-4 mapping in place, and ships a handful of new generator behaviours.
This page lists every change a v1 project must make to upgrade.
1. Bump the dependency
composer require xefi/laravel-osdd:^2.0
2. Breaking — move overrideConfigFrom() to register()
In v1, overrideConfigFrom() deferred its work to app()->booted(). In v2 it applies the merge immediately inside the calling provider's lifecycle — and must therefore run during register(), before any other package's boot() reads the config.
boot() is not a fatal error, but it defeats the whole point of the helper: other packages will have already read their defaults by the time the override applies. Symptoms are subtle — Horizon ignoring horizon.path, Telescope ignoring telescope.middleware, etc.In every layer service provider:
class OsddServiceProvider extends LayerServiceProvider
{
public function boot(): void
{
- $this->overrideConfigFrom(__DIR__ . '/../../config/osdd.php', 'osdd');
+ //
}
public function register(): void
{
- //
+ $this->overrideConfigFrom(__DIR__ . '/../../config/osdd.php', 'osdd');
}
}
Repeat for every overrideConfigFrom(...) call across your functional/ and technical/ layers.
overrideConfigFrom() is now a no-op when config:cache has produced a cached config — same contract as Laravel's own merge helpers.3. Recommended — adopt withRouting() over loadRoutesFrom()
v2 ships a withRouting() helper on LayerServiceProvider that mirrors Laravel's Application::configure()->withRouting(...). It loads web, api, commands, channels, and an optional health endpoint with the right middleware groups and the standard api prefix.
public function boot(): void
{
$this->loadMigrationsFrom(__DIR__ . '/../../database/migrations');
- $this->loadRoutesFrom(__DIR__ . '/../../routes/web.php');
- $this->loadRoutesFrom(__DIR__ . '/../../routes/api.php');
+
+ $this->withRouting(
+ web: __DIR__ . '/../../routes/web.php',
+ api: __DIR__ . '/../../routes/api.php',
+ commands: __DIR__ . '/../../routes/console.php',
+ channels: __DIR__ . '/../../routes/channels.php',
+ );
}
What changes vs. raw loadRoutesFrom():
web:files are wrapped in thewebmiddleware group.api:files are wrapped inapimiddleware and prefixed withapiPrefix(default'api') — drop anyRoute::prefix('api')from inside the file.commands:isrequired only when running in console.channels:isrequired on every request (forBroadcast::channel(...)definitions).- The whole call is a no-op when
route:cachehas produced a cached route file.
For anything beyond these conventions — custom prefixes, domains, named groups — keep using the Route facade directly in boot().
osdd:layer also gained a routes generator that scaffolds the four standard files from stubs:
php artisan osdd:layer functional/orders --generators=routes
# Creates routes/web.php, routes/api.php, routes/console.php, routes/channels.php
4. Restore the App\ PSR-4 mapping
In v1, osdd:start stripped the App\ PSR-4 entry from root composer.json along with Database\Factories\ and Database\Seeders\. v2 keeps the App\ mapping in place so Laravel's Application::getNamespace() still works (some third-party packages call it during bootstrap).
If your project was bootstrapped with v1 and the entry was removed, put it back:
"autoload": {
"psr-4": {
+ "App\\": "app/"
}
}
Then run composer dump-autoload. No code should live under app/ in an OSDD project, but the mapping itself stays.
5. Recommended — re-run osdd:phpunit
v2 of osdd:phpunit adds a <source><exclude><directory>**/database/migrations</directory></exclude></source> block to phpunit.xml so layer migrations don't count against code coverage. The change is idempotent — running it on a v1 phpunit.xml simply adds the exclusion if missing.
php artisan osdd:phpunit
6. Optional — let make commands wire your layer provider
v2 introduces a RegistersInLayerProvider helper used by three make commands. They each inject a line into the resolved layer's service provider when the file doesn't already contain it:
| Command | Statement injected |
|---|---|
osdd:config <name> | $this->overrideConfigFrom(__DIR__ . '/../../config/<name>.php', '<name>'); |
osdd:migration | $this->loadMigrationsFrom(__DIR__ . '/../../database/migrations'); |
osdd:seeder | $this->loadSeeders([\Vendor\Package\…\YourSeeder::class]); |
All three injections are idempotent. Existing v1 projects need no changes — the helper only affects newly generated files. Note that the injected overrideConfigFrom(...) lands in boot(); move it to register() manually when cross-package boot timing matters (see step 2).
7. Optional — ide-helper:models now sees layers
If you use barryvdh/laravel-ide-helper, php artisan ide-helper:models now picks up every layer's src/ directory automatically. Existing ide-helper.model_locations entries are preserved and merged — no config change needed.
8. Other changes
functional/usersstub —osdd:startnow scaffolds aUsersServiceProvider::register()that rebinds Laravel's auth user model withconfig(['auth.providers.users.model' => \Functional\Users\Models\User::class]). Existing v1 projects can either copy that line into their own provider'sregister()or keep their current configuration — both work.- Hyphenated layer names —
osdd:layer external-accountsnow produces a migration that creates theexternal_accountstable (v1 produced an invalid table name on some setups). No action needed for layers already in the repo. - Generated provider — newly scaffolded providers include the
withRouting(...)call by default. Layers generated under v1 keep working unchanged.
Checklist
-
composer require xefi/laravel-osdd:^2.0 - Move every
overrideConfigFrom(...)fromboot()toregister() - (Recommended) Replace
loadRoutesFrom(...)calls withwithRouting(...) - (If v1 stripped it) Re-add
"App\\": "app/"tocomposer.jsonand runcomposer dump-autoload - Re-run
php artisan osdd:phpunitto add the migrations coverage exclusion - Run your test suite — particularly anything that depends on third-party config overrides
Once each step is done you're on v2.