Getting Started

Existing Application

Add layers to an application that keeps its app/ folder, and move domains into them one at a time.

osdd:start is for fresh projects only: it deletes app/ and config/. On an application with code to keep, skip it. Layers then live next to app/, and you move domains into them at your own pace.

1. Install

composer require lomkit/laravel-osdd

The package defaults apply: layers go to functional/ and technical/. To change them, create config/osdd.php by hand with the keys of the configuration reference. The package does not publish it.

2. Create the first layer

php artisan osdd:layer functional/billing --generators=provider,test --composer-update

The command writes functional/billing/composer.json, adds a ./functional/* path repository and a "functional/billing": "*" requirement to the root composer.json, then installs the layer. New code for that domain now goes in the layer, with the osdd:* generators:

php artisan osdd:model Invoice --migration --factory --layer=functional/billing

3. Move existing code into the layer

To move App\Models\Invoice and its table into functional/billing:

  1. Move the class to functional/billing/src/Models/Invoice.php and change its namespace to Functional\Billing\Models. Update the imports that use it: git grep -l 'App\\Models\\Invoice'.
  2. Move its migrations to functional/billing/database/migrations/. Keep their file names: the migrations table records them by name, so migrate does not run them again. The generated layer provider already loads that folder.
  3. Move its factory to functional/billing/database/factories/ under Functional\Billing\Database\Factories, and point the model to it with #[UseFactory(InvoiceFactory::class)].
  4. Move its policy to functional/billing/src/Policies/. Laravel finds Functional\Billing\Policies\InvoicePolicy for Functional\Billing\Models\Invoice on its own.
  5. Move its tests to functional/billing/tests/ under Functional\Billing\Tests.
Class names stored in the database change with the namespace: the *_type columns of polymorphic relations without a morph map, queued jobs, notifications. Register a morph map with Relation::enforceMorphMap() before the move, or update those rows.

4. Seed and test the layers

Layer seeders run with osdd:seed. To run them from db:seed too, call LayersSeeder from your DatabaseSeeder:

database/seeders/DatabaseSeeder.php
use Lomkit\Osdd\Seeders\LayersSeeder;

public function run(): void
{
    $this->call(LayersSeeder::class);
}

Add one test suite per layer to phpunit.xml. The Unit and Feature suites of tests/ stay:

php artisan osdd:phpunit

5. Check the boundaries

php artisan osdd:check

osdd:check only reads the layers, and never reports references to App\ classes: a layer can use app/ code while you move it, and app/ can use the layers. Between layers, the boundary rule applies from the first layer on.

Repeat steps 2 to 5 for each domain.