net-code/laravel-domain
Composer 安装命令:
composer require net-code/laravel-domain
包简介
DDD tactical building blocks (aggregate root, value objects, domain events, typed UUID identifiers, business-rule specification) with optional Laravel integration.
关键字:
README 文档
README
DDD tactical building blocks — the reusable kernel that concrete bounded contexts build on.
The core (NetCode\Domain\*) is pure PHP 8.5+ (only ramsey/uuid); a thin, optional
Laravel integration layer (NetCode\Domain\Laravel\*) wires the kernel into a Laravel app
through an auto-discovered service provider.
Install
composer require net-code/laravel-domain
What's inside
| Class / interface | Purpose |
|---|---|
NetCode\Domain\AggregateRoot |
Base aggregate that records and releases domain events. |
NetCode\Domain\ValueObject |
Base value object with an equals() contract. |
NetCode\Domain\DomainEvent |
Marker interface for events (occurredOn()). |
NetCode\Domain\DomainEventPublisher |
Publisher seam implemented by the host application. |
NetCode\Domain\Identifier\Uuid |
Base for typed UUID identifiers (UUIDv7). |
NetCode\Domain\Rule\BusinessRule |
A single invariant that can be broken. |
NetCode\Domain\Rule\BusinessRuleCode |
Backed-enum contract for machine-readable rule codes. |
NetCode\Domain\Rule\TranslatableRuleParams |
Optional translation parameters for a rule. |
NetCode\Domain\Rule\Specification |
Checks rules and throws BusinessRuleException on the first broken one. |
NetCode\Domain\Rule\BusinessRuleException |
Carries the broken rule's code and translation params. |
NetCode\Domain\Exception\DomainException |
Base for domain-layer exceptions. |
NetCode\Domain\Exception\InvalidArgumentException |
Invalid value-object input. |
Laravel integration (NetCode\Domain\Laravel)
| Class | Purpose |
|---|---|
DomainServiceProvider |
Auto-discovered; binds DomainEventPublisher → LaravelDomainEventPublisher. |
LaravelDomainEventPublisher |
Publishes domain events through Laravel's event dispatcher. |
IdentifierCast |
Eloquent cast between a string column and a typed Identifier\Uuid. |
Usage
Typed identifier
use NetCode\Domain\Identifier\Uuid; final class OrderId extends Uuid {} $id = OrderId::random(); // UUIDv7 $id->equals(OrderId::fromString((string) $id)); // true
Aggregate + domain events
use NetCode\Domain\AggregateRoot; final class Order extends AggregateRoot { public function place(): void { // ... mutate state ... $this->recordThat(new OrderPlaced(/* ... */)); } } $events = $order->releaseEvents(); // hand to your DomainEventPublisher
Business rules via a specification
use NetCode\Domain\Rule\Specification; Specification::check( new OrderMustHaveLines($order), new OrderMustBeUnpaid($order), ); // throws BusinessRuleException on the first broken rule
Specification::check() is a static, stateless guard — call it directly from your aggregates.
There is no instance to construct, inject, or subclass.
Laravel integration
DomainServiceProvider is auto-discovered, so DomainEventPublisher resolves to
LaravelDomainEventPublisher (domain events go through Laravel's dispatcher) with zero wiring.
Cast a model's identifier column to its typed value object:
use Illuminate\Database\Eloquent\Model; use NetCode\Domain\Laravel\IdentifierCast; final class OrderModel extends Model { /** @return array<string, string> */ protected function casts(): array { return ['id' => IdentifierCast::class.':'.OrderId::class]; } }
Development
composer check # pint --test + phpstan (level 8) + phpunit
License
MIT
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 0
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-07-10