Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/next' into layers
Browse files Browse the repository at this point in the history
  • Loading branch information
jaspertey committed Nov 10, 2024
2 parents 42054d4 + 3c73e2d commit 64443a1
Show file tree
Hide file tree
Showing 69 changed files with 1,365 additions and 231 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
All notable changes to `laravel-ddd` will be documented in this file.

## [Unreleased]
### Breaking
- Stubs are now published to `/stubs/ddd/*` instead of `resources/stubs/ddd/*`. If you have ddd stubs published from a prior version, they should be relocated.

### Added
- Experimental: Ability to configure the Application Layer, to generate domain objects that don't typically belong inside the domain layer.
- Ability to configure the Application Layer, to generate domain objects that don't typically belong inside the domain layer.
```php
// In config/ddd.php
'application' => [
Expand All @@ -22,6 +25,7 @@ All notable changes to `laravel-ddd` will be documented in this file.
- Added `ddd:middleware` to generate domain-specific middleware in the application layer.
- Added `ddd:migration` to generate domain migrations.
- Added `ddd:seeder` to generate domain seeders.
- Added `ddd:stub` to list, search, and publish one or more stubs as needed.
- Migration folders across domains will be registered and scanned when running `php artisan migrate`, in addition to the standard application `database/migrations` path.

### Changed
Expand All @@ -40,6 +44,10 @@ All notable changes to `laravel-ddd` will be documented in this file.
### Deprecated
- Domain base models are no longer required by default, and `config('ddd.base_model')` is now `null` by default.

## [1.1.3] - 2024-11-05
### Chore
- Allow `laravel/prompts` dependency to use latest version when possible.

## [1.1.2] - 2024-09-02
### Fixed
- During domain factory autoloading, ensure that `guessFactoryNamesUsing` returns a string when a domain factory is resolved.
Expand Down
79 changes: 52 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Actions: [lorisleiva/laravel-actions](https://github.com/lorisleiva/laravel-acti
```bash
composer require lorisleiva/laravel-actions
```
The default DTO and Action stubs of this package reference classes from these packages. If this doesn't apply to your application, you may customize the stubs accordingly.
The default DTO and Action stubs of this package reference classes from these packages. If this doesn't apply to your application, you may [customize the stubs](#publishing-stubs-advanced) accordingly.

### Deployment
In production, run `ddd:optimize` during the deployment process to [optimize autoloading](#autoloading-in-production).
Expand Down Expand Up @@ -131,7 +131,7 @@ Some objects interact with the domain layer, but are not part of the domain laye
],
],
```
The default configuration above will result in the following:
The configuration above will result in the following:
```bash
ddd:model Invoicing:Invoice --controller --resource --requests
```
Expand All @@ -147,23 +147,8 @@ Output:
│ └─ UpdateInvoiceRequest.php
├─ src/Domain
└─ Invoicing
└─ Models
└─ Invoice.php
```

### Custom Layers (since 1.2)
Some objects interact with the domain layer, but are not part of the domain layer themselves. By default, these include: `controller`, `request`, `middleware`. You may customize the path, namespace, and which `ddd:*` objects belong in the application layer.
```php
// In config/ddd.php
'application' => [
'path' => 'app/Modules',
'namespace' => 'App\Modules',
'objects' => [
'controller',
'request',
'middleware',
],
],
└─ Models
└─ Invoice.php
```

### Nested Objects
Expand Down Expand Up @@ -226,13 +211,49 @@ php artisan ddd:view-model Reporting.Customer:MonthlyInvoicesReportViewModel
```

## Customization
### Config File
This package ships with opinionated (but sensible) configuration defaults. You may customize by publishing the [config file](#config-file) and generator stubs as needed:

```bash
php artisan vendor:publish --tag="ddd-config"
php artisan vendor:publish --tag="ddd-stubs"
php artisan ddd:publish --config
php artisan ddd:publish --stubs
```

### Publishing Stubs (Advanced)
For more granular management of stubs, you may use the `ddd:stub` command:
```bash
# Publish one or more stubs interactively via prompts
php artisan ddd:stub

# Publish all stubs
php artisan ddd:stub --all

# Publish and overwrite only the files that have already been published
php artisan ddd:stub --all --existing

# Overwrite any existing files
php artisan ddd:stub --all --force

# Publish one or more stubs specified as arguments
php artisan ddd:stub model
php artisan ddd:stub model dto action
php artisan ddd:stub controller controller.plain controller.api
```
To publish multiple related stubs at once, use `*` or `.` as a wildcard ending.
```bash
php artisan ddd:stub listener.
```
Output:
```bash
Publishing /stubs/ddd/listener.typed.queued.stub
Publishing /stubs/ddd/listener.queued.stub
Publishing /stubs/ddd/listener.typed.stub
Publishing /stubs/ddd/listener.stub
```
For a quick reference of available stubs, use the `--list` option:
```bash
php artisan ddd:stub --list
```
Note that the extended commands do not publish ddd-specific stubs, and inherit the respective application-level stubs published by Laravel.

## Domain Autoloading and Discovery
Autoloading behaviour can be configured with the `ddd.autoload` configuration option. By default, domain providers, commands, policies, and factories are auto-discovered and registered.
Expand Down Expand Up @@ -338,12 +359,17 @@ return [
| Application Layer
|--------------------------------------------------------------------------
|
| Configure domain objects in the application layer.
| Configure objects that belong in the application layer.
|
| e.g., App\Modules\Invoicing\Controllers\*
| App\Modules\Invoicing\Requests\*
|
*/
'application' => [
'path' => 'app/Modules',
'namespace' => 'App\Modules',

// Specify which ddd:* objects belong in the application layer
'objects' => [
'controller',
'request',
Expand All @@ -353,12 +379,11 @@ return [

/*
|--------------------------------------------------------------------------
| Domain Object Namespaces
| Generator Object Namespaces
|--------------------------------------------------------------------------
|
| This value contains the default namespaces of generated domain
| objects relative to the domain namespace of which the object
| belongs to.
| This array maps the default relative namespaces of generated objects
| relative to their domain's root namespace.
|
| e.g., Domain\Invoicing\Models\*
| Domain\Invoicing\Data\*
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"require": {
"php": "^8.1|^8.2|^8.3",
"illuminate/contracts": "^10.25|^11.0",
"laravel/prompts": "^0.1.16",
"laravel/prompts": "^0.1.16|^0.3.1",
"lorisleiva/lody": "^0.5.0",
"spatie/laravel-package-tools": "^1.13.0"
},
Expand Down
48 changes: 29 additions & 19 deletions config/ddd.php.stub
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,29 @@ return [
*/
'domain_namespace' => {{domain_namespace}},

/*
|--------------------------------------------------------------------------
| Application Layer
|--------------------------------------------------------------------------
|
| Configure objects that belong in the application layer.
|
| e.g., App\Modules\Invoicing\Controllers\*
| App\Modules\Invoicing\Requests\*
|
*/
'application' => [
'path' => 'app/Modules',
'namespace' => 'App\Modules',

// Specify which ddd:* objects belong in the application layer
'objects' => [
'controller',
'request',
'middleware',
],
],

/*
|--------------------------------------------------------------------------
| Domain Object Namespaces
Expand All @@ -48,6 +71,7 @@ return [
'class' => '',
'channel' => 'Channels',
'command' => 'Commands',
'controller' => 'Controllers',
'enum' => 'Enums',
'event' => 'Events',
'exception' => 'Exceptions',
Expand All @@ -56,13 +80,17 @@ return [
'job' => 'Jobs',
'listener' => 'Listeners',
'mail' => 'Mail',
'middleware' => 'Middleware',
'migration' => 'Database\Migrations',
'notification' => 'Notifications',
'observer' => 'Observers',
'policy' => 'Policies',
'provider' => 'Providers',
'resource' => 'Resources',
'request' => 'Requests',
'rule' => 'Rules',
'scope' => 'Scopes',
'seeder' => 'Database\Seeders',
'trait' => '',
],

Expand Down Expand Up @@ -125,29 +153,11 @@ return [
|
*/
'autoload' => [
/**
* When enabled, any class within the domain layer extending `Illuminate\Support\ServiceProvider`
* will be auto-registered as a service provider
*/
'providers' => true,

/**
* When enabled, any class within the domain layer extending `Illuminate\Console\Command`
* will be auto-registered as a command when running in console.
*/
'commands' => true,

/**
* When enabled, the package will register a custom policy discovery callback to resolve policy names
* for domain models, and fallback to Laravel's default for all other cases.
*/
'policies' => true,

/**
* When enabled, the package will register a custom factory discovery callback to resolve factory names
* for domain models, and fallback to Laravel's default for all other cases.
*/
'factories' => true,
'migrations' => true,
],

/*
Expand Down
70 changes: 70 additions & 0 deletions src/Commands/Concerns/HasDomainStubs.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

namespace Lunarstorm\LaravelDDD\Commands\Concerns;

use Illuminate\Support\Str;
use Lunarstorm\LaravelDDD\Facades\DDD;

trait HasDomainStubs
{
protected static $usingPublishedStub = false;

protected function usingPublishedStub($usingPublishedStub = true)
{
static::$usingPublishedStub = $usingPublishedStub;

return $this;
}

protected function isUsingPublishedStub(): bool
{
return static::$usingPublishedStub;
}

protected function getStub()
{
$stub = parent::getStub();

if ($publishedStub = $this->resolvePublishedDddStub($stub)) {
$stub = $publishedStub;
}

$this->usingPublishedStub(str($stub)->startsWith(app()->basePath('stubs')));

return $stub;
}

protected function resolvePublishedDddStub($path)
{
$stubFilename = str($path)
->basename()
->ltrim('/\\')
->toString();

// Check if there is a user-published stub
if (file_exists($publishedPath = app()->basePath('stubs/ddd/'.$stubFilename))) {
return $publishedPath;
}

// Also check for legacy stub extensions
if (file_exists($legacyPublishedPath = Str::replaceLast('.stub', '.php.stub', $publishedPath))) {
return $legacyPublishedPath;
}

return null;
}

protected function resolveDddStubPath($path)
{
$path = str($path)
->basename()
->ltrim('/\\')
->toString();

if ($publishedPath = $this->resolvePublishedDddStub($path)) {
return $publishedPath;
}

return DDD::packagePath('stubs/'.$path);
}
}
32 changes: 32 additions & 0 deletions src/Commands/Concerns/InteractsWithStubs.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Lunarstorm\LaravelDDD\Commands\Concerns;

trait InteractsWithStubs
{
protected function fillPlaceholder($stub, $placeholder, $value)
{
return str_replace(["{{$placeholder}}", "{{ $placeholder }}"], $value, $stub);
}

protected function preparePlaceholders(): array
{
return [];
}

protected function applyPlaceholders($stub)
{
$placeholders = $this->preparePlaceholders();

foreach ($placeholders as $placeholder => $value) {
$stub = $this->fillPlaceholder($stub, $placeholder, $value ?? '');
}

return $stub;
}

protected function buildClass($name)
{
return $this->applyPlaceholders(parent::buildClass($name));
}
}
6 changes: 5 additions & 1 deletion src/Commands/DomainActionMakeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

namespace Lunarstorm\LaravelDDD\Commands;

use Lunarstorm\LaravelDDD\Commands\Concerns\HasDomainStubs;

class DomainActionMakeCommand extends DomainGeneratorCommand
{
use HasDomainStubs;

protected $name = 'ddd:action';

/**
Expand All @@ -17,7 +21,7 @@ class DomainActionMakeCommand extends DomainGeneratorCommand

protected function getStub()
{
return $this->resolveStubPath('action.php.stub');
return $this->resolveDddStubPath('action.stub');
}

protected function preparePlaceholders(): array
Expand Down
Loading

0 comments on commit 64443a1

Please sign in to comment.