All notable changes to laravel-ddd
will be documented in this file.
- Stubs are now published to
base_path('stubs/ddd')
instead ofresource_path('stubs/ddd')
. In other words, they are now co-located alongside the framework's published stubs, within a ddd subfolder. - Published stubs now use
.stub
extension instead of.php.stub
(following Laravel's convention). - If you are using published stubs from pre 1.2, you will need to refactor your stubs accordingly.
- Support for the Application Layer, to generate domain-specific objects that don't belong directly in the domain layer:
// In config/ddd.php 'application_path' => 'app/Modules', 'application_namespace' => 'App\Modules', 'application_objects' => [ 'controller', 'request', 'middleware', ],
- Support for Custom Layers, additional top-level namespaces of your choosing, such as
Infrastructure
,Integrations
, etc.:// In config/ddd.php 'layers' => [ 'Infrastructure' => 'src/Infrastructure', ],
- Added config utility command
ddd:config
to help manage the package's configuration over time. - Added stub utility command
ddd:stub
to publish one or more stubs selectively. - Added
ddd:controller
to generate domain-specific controllers. - Added
ddd:request
to generate domain-spefic requests. - Added
ddd:middleware
to generate domain-specific middleware. - Added
ddd:migration
to generate domain migrations. - Added
ddd:seeder
to generate domain seeders. - Added
ddd:stub
to manage stubs. - Migration folders across domains will be registered and scanned when running
php artisan migrate
, in addition to the standard applicationdatabase/migrations
path. - Ability to customize generator object naming conventions with your own logic using
DDD::resolveObjectSchemaUsing()
.
ddd:model
now extends Laravel's nativemake:model
and inherits all standard options:--migration|-m
--factory|-f
--seed|-s
--controller --resource --requests|-crR
--policy
-mfsc
--all|-a
--pivot|-p
ddd:cache
is nowddd:optimize
(ddd:cache
is still available as an alias).- Since Laravel 11.27.1, the framework's
optimize
andoptimize:clear
commands will automatically invokeddd:optimize
(ddd:cache
) andddd:clear
respectively.
- Domain base models are no longer required by default, and
config('ddd.base_model')
is nownull
by default. - Stubs are no longer published via
php artisan vendor:publish --tag="ddd-stubs"
. Instead, usephp artisan ddd:stub
to manage them.
- Allow
laravel/prompts
dependency to use latest version when possible.
- During domain factory autoloading, ensure that
guessFactoryNamesUsing
returns a string when a domain factory is resolved. - Resolve issues with failing tests caused by mutations to
composer.json
that weren't rolled back.
- Ability to ignore folders during autoloading via
config('ddd.autoload_ignore')
, or register a custom filter callback viaDDD::filterAutoloadPathsUsing(callable $filter)
.
/*
|--------------------------------------------------------------------------
| Autoload Ignore Folders
|--------------------------------------------------------------------------
|
| Folders that should be skipped during autoloading discovery,
| relative to the root of each domain.
|
| e.g., src/Domain/Invoicing/<folder-to-ignore>
|
| If more advanced filtering is needed, a callback can be registered
| using `DDD::filterAutoloadPathsUsing(callback $filter)` in
| the AppServiceProvider's boot method.
|
*/
'autoload_ignore' => [
'Tests',
'Database/Migrations',
],
- Internals: Domain cache is no longer quietly cleared on laravel's
cache:clearing
event, so thatddd:cache
yields consistent results no matter which order it runs in production (before or aftercache:clear
oroptimize:clear
commands).
- Add
ddd:class
generator extending Laravel'smake:class
(Laravel 11 only). - Add
ddd:interface
generator extending Laravel'smake:interface
(Laravel 11 only). - Add
ddd:trait
generator extending Laravel'smake:trait
(Laravel 11 only). - Allow overriding configured namespaces at runtime by specifying an absolute name starting with /:
# The usual: generate a provider in the configured provider namespace
php artisan ddd:provider Invoicing:InvoiceServiceProvider
# -> Domain\Invoicing\Providers\InvoiceServiceProvider
# Override the configured namespace at runtime
php artisan ddd:provider Invoicing:/InvoiceServiceProvider
# -> Domain\Invoicing\InvoiceServiceProvider
# Generate an event inside the Models namespace (hypothetical)
php artisan ddd:event Invoicing:/Models/EventDoesNotBelongHere
# -> Domain\Invoicing\Models\EventDoesNotBelongHere
# Deep nesting is supported
php artisan ddd:exception Invoicing:/Models/Exceptions/InvoiceNotFoundException
# -> Domain\Invoicing\Models\Exceptions\InvoiceNotFoundException
- Internals: Handle a variety of additional edge cases when generating base models and base view models.
ddd:list
to show a summary of current domains in the domain folder.- For all generator commands, if a domain isn't specified, prompt for it with auto-completion suggestions based on the contents of the root domain folder.
- Command aliases for some generators:
- Data Transfer Object:
ddd:dto
,ddd:data
,ddd:data-transfer-object
,ddd:datatransferobject
- Value Object:
ddd:value
,ddd:valueobject
,ddd:value-object
- View Model:
ddd:view-model
,ddd:viewmodel
- Data Transfer Object:
- Additional generators that extend Laravel's generators and funnel the generated objects into the domain layer:
ddd:cast {domain}:{name}
ddd:channel {domain}:{name}
ddd:command {domain}:{name}
ddd:enum {domain}:{name}
(Laravel 11 only)ddd:event {domain}:{name}
ddd:exception {domain}:{name}
ddd:job {domain}:{name}
ddd:listener {domain}:{name}
ddd:mail {domain}:{name}
ddd:notification {domain}:{name}
ddd:observer {domain}:{name}
ddd:policy {domain}:{name}
ddd:provider {domain}:{name}
ddd:resource {domain}:{name}
ddd:rule {domain}:{name}
ddd:scope {domain}:{name}
- Support for autoloading and discovery of domain service providers, commands, policies, and factories.
- (BREAKING) For applications that published the config prior to this release, config should be removed, re-published, and re-configured.
- (BREAKING) Generator commands no longer receive a domain argument. Instead of
ddd:action Invoicing CreateInvoice
, one of the following would be used:- Using the --domain option:
ddd:action CreateInvoice --domain=Invoicing
(this takes precedence). - Shorthand syntax:
ddd:action Invoicing:CreateInvoice
. - Or simply
ddd:action CreateInvoice
to be prompted for the domain afterwards.
- Using the --domain option:
- Improved the reliability of generating base view models when
ddd.base_view_model
is something other than the defaultDomain\Shared\ViewModels\ViewModel
. - Domain factories are now generated inside the domain layer under the configured factory namespace
ddd.namespaces.factory
(defaultDatabase\Factories
). Factories located in/database/factories/<domain>/*
(v0.x) will continue to work as a fallback when attempting to resolve a domain model's factory. - Minimum supported Laravel version is now 10.25.
- Dropped Laravel 9 support.
- Add
ddd.domain_path
andddd.domain_namespace
to config, to specify the path to the domain layer and root domain namespace more explicitly (replaces the previousddd.paths.domains
config). - Implement
Lunarstorm\LaravelDDD\Factories\HasDomainFactory
trait which can be used on domain models that are unable to extend the base domain model.
- Default
base-model.php.stub
now utilizes theHasDomainFactory
trait.
- Config
ddd.paths.domains
deprecated in favour ofddd.domain_path
andddd.domain_namespace
. Existing config files published prior to this release should removeddd.paths.domains
and addddd.domain_path
andddd.domain_namespace
accordingly.
- Internals: normalize generator file paths using
DIRECTORY_SEPARATOR
for consistency across different operating systems when it comes to console output and test expectations.
- Add Laravel 11 support.
- Add PHP 8.3 support.
- Update dependencies.
- Implement proper support for custom base models when using
ddd:model
:- If the configured
ddd.base_model
exists (evaluated usingclass_exists
), base model generation is skipped. - If
ddd.base_model
does not exist and falls under a domain namespace, base model will be generated. - Falling under a domain namespace means
Domain\**\Models\**
. - If
ddd.base_model
were set toApp\Models\NonExistentModel
orIlluminate\Database\Eloquent\NonExistentModel
, they fall outside of the domain namespace and will not be generated for you.
- If the configured
- Resolve long-standing issue where
ddd:model
would not properly detect whether the configuredddd.base_model
already exists, leading to unintended results.
- Update composer dependencies.
- The default domain model stub
model.php.stub
has changed. If stubs were published prior to this release, you may have to delete and re-publish; unless the publishedmodel.php.stub
has been entirely customized with independent logic for your respective application.
- Formal support for subdomains (nested domains). For example, to generate model
Domain\Reporting\Internal\Models\InvoiceReport
, the domain argument can be specified with dot notation:ddd:model Reporting.Internal InvoiceReport
. SpecifyingReporting/Internal
orReporting\\Internal
will also be accepted and normalized to dot notation internally. - Implement abstract
Lunarstorm\LaravelDDD\Factories\DomainFactory
extension ofIlluminate\Database\Eloquent\Factories\Factory
:- Implements
DomainFactory::resolveFactoryName()
to resolve the corresponding factory for a domain model. - Will resolve the correct factory if the model belongs to a subdomain;
Domain\Reporting\Internal\Models\InvoiceReport
will correctly resolve toDatabase\Factories\Reporting\Internal\InvoiceReportFactory
.
- Implements
- Default base model implementation in
base-model.php.stub
now usesDomainFactory::factoryForModel()
inside thenewFactory
method to resolve the model factory.
- For existing installations of the package to support sub-domain model factories, the base model's
newFactory()
should be updated where applicable; seebase-model.php.stub
.
use Lunarstorm\LaravelDDD\Factories\DomainFactory;
// ...
protected static function newFactory()
{
return DomainFactory::factoryForModel(get_called_class());
}
- Ensure generated domain factories set the
protected $model
property. - Ensure generated factory classes are always suffixed by
Factory
.
- Ability to generate domain model factories, in a few ways:
ddd:factory Invoicing InvoiceFactory
ddd:model Invoicing Invoice --factory
ddd:model Invoicing Invoice -f
ddd:model -f
(if relying on prompts)
- Clean up default stubs; get rid of extraneous ellipses in comment blocks and ensure code style is consistent.
- Ensure generator commands show a nicely sanitized path to generated file in the console output (previously, double slashes were present). Only applies to Laravel 9.32.0 onwards, when file paths were added to the console output.
- Upgrade test suite to use Pest 2.x.
- Ability to generate actions (
ddd:action
), which by default generates an action class based on thelorisleiva/laravel-actions
package.
- Minor cleanups and updates to the default
ddd.php
config file. - Update stubs to be less opinionated where possible.
- Update argument definitions across generator commands to play nicely with
PromptsForMissingInput
behaviour introduced in Laravel v9.49.0.
- Ensure the configured domain path and namespace is respected by
ddd:base-model
andddd:base-view-model
.
- Increase test coverage to ensure expected namespaces are present in generated objects.
- Domain generator commands will infer the root domain namespace based on the configured
ddd.paths.domains
. - Change the default domain path in config to
src/Domain
(was previouslysrc/Domains
), thereby generating objects with the singularDomain
root namespace.
- Support for Laravel 10.
- Install command now publishes config, registers the default domain path in composer.json, and prompts to publish stubs.
- Generator command signatures simplified to
ddd:*
(previouslyddd:make:*
).
- When ViewModels are generated, base view model import statement is now properly substituted.
- Early version of generator commands for domain models, dto, value objects, view models.
ddd:install
command to automatically register the domain folder inside the application's composer.json (experimental)