Upgrade

v1 → v2

Migrate an existing Laravel OSDD v1 project to 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

Terminal
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.

Leaving the call in 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:

src/Providers/OsddServiceProvider.php
 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.

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.

src/Providers/OrdersServiceProvider.php
 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 the web middleware group.
  • api: files are wrapped in api middleware and prefixed with apiPrefix (default 'api') — drop any Route::prefix('api') from inside the file.
  • commands: is required only when running in console.
  • channels: is required on every request (for Broadcast::channel(...) definitions).
  • The whole call is a no-op when route:cache has 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:

Terminal
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:

composer.json
 "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.

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.

Terminal
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:

CommandStatement 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/users stubosdd:start now scaffolds a UsersServiceProvider::register() that rebinds Laravel's auth user model with config(['auth.providers.users.model' => \Functional\Users\Models\User::class]). Existing v1 projects can either copy that line into their own provider's register() or keep their current configuration — both work.
  • Hyphenated layer namesosdd:layer external-accounts now produces a migration that creates the external_accounts table (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(...) from boot() to register()
  • (Recommended) Replace loadRoutesFrom(...) calls with withRouting(...)
  • (If v1 stripped it) Re-add "App\\": "app/" to composer.json and run composer dump-autoload
  • Re-run php artisan osdd:phpunit to 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.