关于Laravel中MVC架构下使用DDD的意义、示例及项目咨询
Laravel中结合DDD的意义与实践示例
1. 在Laravel中结合DDD的意义
- 聚焦业务核心,避免"贫血模型":Laravel默认MVC模式下,Model常沦为数据库操作载体,业务逻辑散落在Controller、Helper甚至路由中,后期维护难度陡增。DDD通过领域实体封装核心业务规则,让代码围绕业务本身而非技术实现,确保业务逻辑的内聚性。
- 拆分复杂业务,降低耦合:当项目涉及复杂业务(如电商订单流转、金融交易规则),DDD的限界上下文、聚合根等概念能帮你把大业务拆分成独立的、职责清晰的模块,Laravel的依赖注入、服务容器特性可以很好地支撑这种模块化架构,避免模块间互相干扰。
- 提升代码复用性与可测试性:领域层代码不依赖Laravel框架细节(比如Eloquent ORM),可轻松在其他项目复用;同时,领域逻辑脱离数据库和框架环境,单元测试无需依赖数据库连接,编写和执行更高效。
- 统一团队沟通语言:DDD强调通用语言,让产品、开发、测试团队用统一的业务术语沟通,减少理解偏差,Laravel的目录结构可调整为贴合DDD分层的模式,新人能更快理解项目的业务逻辑架构。
2. MVC架构中使用DDD的Laravel示例
下面以电商订单场景为例,展示如何在Laravel中融入轻量化DDD实践(并非严格全DDD实现,适配Laravel生态):
调整目录结构
app/ ├── Domain/ # 领域层:封装核心业务逻辑,不依赖框架 │ ├── Order/ │ │ ├── Entities/ │ │ │ └── Order.php # 聚合根,包含订单核心规则 │ │ ├── ValueObjects/ │ │ │ └── OrderStatus.php # 值对象,约束订单状态合法值 │ │ ├── Repositories/ │ │ │ └── OrderRepositoryInterface.php # 仓储接口,定义数据操作契约 │ │ └── Exceptions/ │ │ └── InvalidOrderException.php # 领域异常 ├── Infrastructure/ # 基础设施层:实现领域层接口,对接框架/外部服务 │ ├── Repositories/ │ │ └── EloquentOrderRepository.php # 用Eloquent实现仓储接口 ├── Application/ # 应用层:处理用户用例,协调领域层与基础设施 │ └── Order/ │ └── CreateOrderUseCase.php ├── Http/ # 表现层:对应MVC的Controller,处理HTTP请求 │ └── Controllers/ │ └── OrderController.php
核心代码示例
领域实体:Order.php
namespace App\Domain\Order\Entities; use App\Domain\Order\ValueObjects\OrderStatus; use App\Domain\Order\Exceptions\InvalidOrderException; class Order { private string $id; private array $items; private float $totalAmount; private OrderStatus $status; public function __construct(string $id, array $items, float $totalAmount) { $this->id = $id; $this->validateItems($items); $this->items = $items; $this->totalAmount = $totalAmount; $this->status = OrderStatus::PENDING; } // 业务方法:标记订单为已支付 public function markAsPaid(): void { if ($this->status !== OrderStatus::PENDING) { throw new InvalidOrderException('仅待支付订单可标记为已支付'); } $this->status = OrderStatus::PAID; } // 内部验证逻辑 private function validateItems(array $items): void { if (empty($items)) { throw new InvalidOrderException('订单不能没有商品'); } foreach ($items as $item) { if (!isset($item['product_id'], $item['quantity']) || $item['quantity'] <= 0) { throw new InvalidOrderException('商品信息不合法'); } } } // 仅暴露必要的getter,避免外部直接修改属性 public function getId(): string { return $this->id; } public function getStatus(): OrderStatus { return $this->status; } public function getTotalAmount(): float { return $this->totalAmount; } public function getItems(): array { return $this->items; } }
值对象:OrderStatus.php
namespace App\Domain\Order\ValueObjects; enum OrderStatus: string { case PENDING = 'pending'; case PAID = 'paid'; case SHIPPED = 'shipped'; case CANCELLED = 'cancelled'; // 确保状态值合法 public static function fromString(string $value): self { foreach (self::cases() as $status) { if ($status->value === $value) { return $status; } } throw new \InvalidArgumentException("无效的订单状态:$value"); } }
仓储接口:OrderRepositoryInterface.php
namespace App\Domain\Order\Repositories; use App\Domain\Order\Entities\Order; interface OrderRepositoryInterface { public function save(Order $order): void; public function findById(string $id): ?Order; }
基础设施层实现:EloquentOrderRepository.php
namespace App\Infrastructure\Repositories; use App\Domain\Order\Entities\Order; use App\Domain\Order\Repositories\OrderRepositoryInterface; use App\Models\Order as EloquentOrderModel; class EloquentOrderRepository implements OrderRepositoryInterface { public function save(Order $order): void { EloquentOrderModel::updateOrCreate( ['id' => $order->getId()], [ 'items' => $order->getItems(), 'total_amount' => $order->getTotalAmount(), 'status' => $order->getStatus()->value, ] ); } public function findById(string $id): ?Order { $model = EloquentOrderModel::find($id); if (!$model) { return null; } return new Order( $model->id, $model->items, $model->total_amount ); } }
应用层用例:CreateOrderUseCase.php
namespace App\Application\Order; use App\Domain\Order\Entities\Order; use App\Domain\Order\Repositories\OrderRepositoryInterface; use Ramsey\Uuid\Uuid; class CreateOrderUseCase { public function __construct(private OrderRepositoryInterface $repository) {} public function execute(array $items, float $totalAmount): void { $orderId = Uuid::uuid4()->toString(); $order = new Order($orderId, $items, $totalAmount); $this->repository->save($order); } }
表现层Controller:OrderController.php
namespace App\Http\Controllers; use App\Application\Order\CreateOrderUseCase; use Illuminate\Http\Request; class OrderController extends Controller { public function store(Request $request, CreateOrderUseCase $useCase) { $validated = $request->validate([ 'items' => 'required|array', 'items.*.product_id' => 'required|string', 'items.*.quantity' => 'required|integer|min:1', 'total_amount' => 'required|numeric|min:0', ]); $useCase->execute($validated['items'], $validated['total_amount']); return response()->json(['message' => '订单创建成功'], 201); } }
关于找不到Laravel DDD项目的说明
大部分Laravel项目不会采用严格的全DDD架构,而是根据业务复杂度选择性融入DDD实践(比如值对象、仓储模式、领域实体),因为全DDD对中小项目来说成本过高。你可以在GitHub上搜索laravel ddd找到部分示例项目,很多企业级的DDD Laravel项目可能因业务敏感未开源,但上述轻量化实践已经能覆盖大部分复杂业务场景。
内容的提问来源于stack exchange,提问作者mahdi msr
相关产品推荐
相关产品推荐

