You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 12:59:50