Skip to content

Commit 64a048a

Browse files
author
Florian Krämer
committed
Fixing layer rules
1 parent ccc0c27 commit 64a048a

File tree

4 files changed

+22
-17
lines changed

4 files changed

+22
-17
lines changed

data/ModularArchitectureTest/Capability/UserManagement/Presentation/AdminAPI/Controller/UserController.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
namespace App\Capability\UserManagement\Presentation\AdminAPI\Controller;
66

77
use App\Capability\UserManagement\Application\UseCases\CreateUser\CreateUser;
8-
use App\Capability\UserManagement\Domain\Model\User;
98

109
/**
11-
* Valid controller - Presentation can import from Application and Domain
10+
* Valid controller - Presentation can import from Application
1211
*/
1312
class UserController
1413
{

docs/Rules.md

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,15 @@ Enforces strict dependency rules for modular hexagonal (Ports and Adapters) arch
9595

9696
**What it enforces:**
9797

98-
1. **Intra-Module Layer Dependencies** - Within the same module (default configuration):
99-
- Domain: Cannot import from Application, Infrastructure, or Presentation
100-
- Application: Can import Domain; cannot import Infrastructure or Presentation
101-
- Infrastructure: Can import Domain and Application; cannot import Presentation
102-
- Presentation: Can import Application and Domain; cannot import Infrastructure
98+
1. **Intra-Module Layer Dependencies** - Within the same module (default Clean Architecture configuration):
99+
- **Domain**: Cannot import from any other layer (pure business logic)
100+
- **Application**: Can import Domain only (defines use cases and port interfaces)
101+
- **Infrastructure**: Can import Domain and Application (implements port interfaces defined in Application)
102+
- **Presentation**: Can import Application only (calls use cases)
103103
- **All layers can import from themselves** (e.g., Presentation → Presentation within the same layer)
104104

105+
This follows the **Dependency Inversion Principle**: Application defines interfaces, Infrastructure implements them.
106+
105107
**Note:** You can customize these layer dependencies to match your architecture needs (see configuration examples below).
106108

107109
2. **Cross-Module Dependencies** - Between different modules:
@@ -134,7 +136,7 @@ src/Capability/
134136
class: Phauthentic\PHPStanRules\Architecture\ModularArchitectureRule
135137
arguments:
136138
baseNamespace: 'App\Capability'
137-
layerDependencies: null # Uses default layer rules
139+
layerDependencies: null # Uses default Clean Architecture rules
138140
allowedCrossModulePatterns:
139141
- '/Facade$/' # Classes ending with "Facade"
140142
- '/FacadeInterface$/' # Classes ending with "FacadeInterface"
@@ -186,9 +188,13 @@ src/Capability/
186188
**Parameters:**
187189

188190
- `baseNamespace`: The base namespace for your capabilities/modules (e.g., `App\Capability`)
189-
- `layerDependencies`: (Optional) Custom layer dependency rules. If not provided, uses default hexagonal architecture rules.
191+
- `layerDependencies`: (Optional) Custom layer dependency rules. If not provided, uses default Clean Architecture rules.
190192
- Format: `LayerName: [AllowedDependency1, AllowedDependency2, ...]`
191-
- Default layers: Domain, Application, Infrastructure, Presentation
193+
- Default layers (following Dependency Inversion Principle):
194+
- `Domain: []` - Pure business logic
195+
- `Application: [Domain]` - Use cases and port interfaces
196+
- `Infrastructure: [Domain, Application]` - Implements Application interfaces
197+
- `Presentation: [Application]` - Controllers, CLI commands
192198
- You can define any custom layer names you need
193199
- `allowedCrossModulePatterns`: **Required** - Regex patterns for fully qualified class names that can be imported across modules.
194200
- **No defaults** - you must explicitly configure which classes can cross module boundaries
@@ -230,13 +236,13 @@ use App\Capability\UserManagement\Domain\Model\User;
230236

231237
The rule is flexible and allows you to define your own architectural layers beyond the defaults. Here are some common use cases:
232238

233-
1. **Allow Application to depend on Infrastructure** (for repositories):
239+
1. **Stricter Isolation** (Infrastructure cannot see Application):
234240
```neon
235241
layerDependencies:
236242
Domain: []
237-
Application: [Domain, Infrastructure] # Application can now use Infrastructure
238-
Infrastructure: [Domain]
239-
Presentation: [Application, Domain]
243+
Application: [Domain]
244+
Infrastructure: [Domain] # Infrastructure isolated from Application
245+
Presentation: [Application]
240246
```
241247

242248
2. **Three-Tier Architecture** (instead of hexagonal):

src/Architecture/ModularArchitectureRule.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ private function getDefaultLayerDependencies(): array
7676
{
7777
return [
7878
self::LAYER_DOMAIN => [],
79-
self::LAYER_APPLICATION => [self::LAYER_DOMAIN, self::LAYER_INFRASTRUCTURE],
79+
self::LAYER_APPLICATION => [self::LAYER_DOMAIN],
8080
self::LAYER_INFRASTRUCTURE => [self::LAYER_DOMAIN, self::LAYER_APPLICATION],
81-
self::LAYER_PRESENTATION => [self::LAYER_DOMAIN, self::LAYER_APPLICATION],
81+
self::LAYER_PRESENTATION => [self::LAYER_APPLICATION],
8282
];
8383
}
8484

tests/TestCases/Architecture/ModularArchitectureRuleTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public function testPresentationCannotImportInfrastructure(): void
9595

9696
public function testValidPresentationImports(): void
9797
{
98-
// Presentation can import from Application and Domain (valid)
98+
// Presentation can import from Application (valid)
9999
$this->analyse(
100100
[__DIR__ . '/../../../data/ModularArchitectureTest/Capability/UserManagement/Presentation/AdminAPI/Controller/UserController.php'],
101101
[]

0 commit comments

Comments
 (0)