php-ddd/domain-driven-design-bundle
A Laravel bundle for applying domain-driven design: aggregates, entities, value objects, domain events, and repositories with clean separation between domain, application, and infrastructure layers.
Start by installing the package and immediately publishing its configuration, since nearly all day-to-day behavior is driven from a single root config node:
composer require --dev <vendor>/<package>
php artisan vendor:publish --provider="<Vendor>\<Package>\<PackageServiceProvider>"
As of v0.1.1 the published file is config/domain_driven_design.php and the root key is domain_driven_design. If you are coming from v0.1.0 or earlier, the key was php_ddd_domain_driven_design; treat that name as gone.
Where to look first:
config/domain_driven_design.php — path roots, namespace mappings, and any generator settings.make:* / domain:* commands exposed by the package; these are usually the fastest way to see the expected directory layout.A sensible first use case is to scaffold one bounded context end-to-end and verify that Laravel can autoload it, resolve its bindings, and run its migrations/tests before you add a second context. This validates your namespace and path configuration early, when it is cheap to change.
Config-first domain registration. Keep the published config as the single source of truth for where domains live and how they map to namespaces. Prefer adding a new entry per bounded context over relying on implicit convention, so that refactors and moves are a config change rather than a codebase-wide search.
One bounded context per directory. A typical layout under the configured root is app/Domains/<Context>/{Domain,Application,Infrastructure}. Register each context's service provider from the package config or a small parent provider, and let Laravel's container handle wiring inside the context.
Bind interfaces in the infrastructure layer. Keep domain and application code dependent on interfaces, and bind concrete implementations in each context's provider. This keeps the package's config concerns (paths, namespaces) separate from your dependency inversion concerns.
Generate, then edit. Use the package's generators to produce the skeleton, then immediately move business rules into the generated classes. Generated code is a starting point; the value comes from the structure it enforces, not from leaving it untouched.
Test at the context boundary. Write feature tests that boot a single context's provider and exercise its public application services. This catches namespace/path misconfiguration quickly and keeps contexts from silently coupling.
php_ddd_domain_driven_design to domain_driven_design, including config('php_ddd_domain_driven_design...') calls, custom config files, and any .env keys that mirror the old name. Delete the stale published config file rather than leaving both, to avoid a split-brain configuration.php artisan config:clear and, in deployed environments, re-run php artisan config:cache. A cached old config key is the most likely cause of "my paths are ignored" after the rename.composer.json psr-4 (or the classmap), followed by composer dump-autoload. If a freshly generated domain "does not exist," check autoload before checking the package config.config:cache will not serialize closures. Keep config declarative and resolve runtime values in providers.0.x version and a rename in a patch release, pin the package in composer.json and read the release notes before every bump. Expect further config-key churn while the API stabilizes.How can I help you explore Laravel packages today?