PHP 怎么PHP DDD 示例

wen PHP项目 2

本文目录导读:

PHP 怎么PHP DDD 示例

  1. 领域层(Domain Layer)
  2. 应用层(Application Layer)
  3. 基础设施层(Infrastructure Layer)
  4. 使用示例
  5. 目录结构

我来给你展示一个完整的PHP DDD(领域驱动设计)示例,这里以一个简单的订单系统为例:

领域层(Domain Layer)

值对象(Value Objects)

<?php
// Domain/ValueObject/Money.php
namespace App\Domain\ValueObject;
class Money
{
    private float $amount;
    private string $currency;
    public function __construct(float $amount, string $currency = 'CNY')
    {
        if ($amount < 0) {
            throw new \InvalidArgumentException('金额不能为负数');
        }
        $this->amount = $amount;
        $this->currency = $currency;
    }
    public function getAmount(): float
    {
        return $this->amount;
    }
    public function getCurrency(): string
    {
        return $this->currency;
    }
    public function add(Money $money): Money
    {
        if ($this->currency !== $money->currency) {
            throw new \InvalidArgumentException('货币不一致');
        }
        return new Money($this->amount + $money->amount, $this->currency);
    }
    public function equals(Money $money): bool
    {
        return $this->amount === $money->amount 
            && $this->currency === $money->currency;
    }
}

实体(Entities)

<?php
// Domain/Entity/Order.php
namespace App\Domain\Entity;
use App\Domain\ValueObject\Money;
use App\Domain\ValueObject\OrderStatus;
class Order
{
    private string $id;
    private string $customerId;
    private array $items = [];
    private Money $totalAmount;
    private OrderStatus $status;
    private \DateTimeImmutable $createdAt;
    private ?\DateTimeImmutable $paidAt = null;
    public function __construct(string $id, string $customerId)
    {
        $this->id = $id;
        $this->customerId = $customerId;
        $this->totalAmount = new Money(0);
        $this->status = new OrderStatus(OrderStatus::PENDING);
        $this->createdAt = new \DateTimeImmutable();
    }
    public function addItem(OrderItem $item): void
    {
        $this->items[] = $item;
        $this->recalculateTotal();
    }
    public function removeItem(string $itemId): void
    {
        $this->items = array_filter(
            $this->items,
            fn(OrderItem $item) => $item->getId() !== $itemId
        );
        $this->recalculateTotal();
    }
    public function pay(): void
    {
        if ($this->status->getValue() !== OrderStatus::PENDING) {
            throw new \DomainException('只有待支付订单才能支付');
        }
        if ($this->totalAmount->getAmount() <= 0) {
            throw new \DomainException('订单金额必须大于0');
        }
        $this->status = new OrderStatus(OrderStatus::PAID);
        $this->paidAt = new \DateTimeImmutable();
    }
    public function cancel(): void
    {
        if (!in_array($this->status->getValue(), [OrderStatus::PENDING, OrderStatus::PAID])) {
            throw new \DomainException('当前状态不能取消');
        }
        $this->status = new OrderStatus(OrderStatus::CANCELLED);
    }
    private function recalculateTotal(): void
    {
        $total = new Money(0);
        foreach ($this->items as $item) {
            $total = $total->add($item->getSubtotal());
        }
        $this->totalAmount = $total;
    }
    // Getters...
    public function getId(): string { return $this->id; }
    public function getCustomerId(): string { return $this->customerId; }
    public function getItems(): array { return $this->items; }
    public function getTotalAmount(): Money { return $this->totalAmount; }
    public function getStatus(): OrderStatus { return $this->status; }
    public function getCreatedAt(): \DateTimeImmutable { return $this->createdAt; }
    public function getPaidAt(): ?\DateTimeImmutable { return $this->paidAt; }
}
<?php
// Domain/Entity/OrderItem.php
namespace App\Domain\Entity;
use App\Domain\ValueObject\Money;
class OrderItem
{
    private string $id;
    private string $productId;
    private string $productName;
    private Money $price;
    private int $quantity;
    public function __construct(
        string $id,
        string $productId,
        string $productName,
        Money $price,
        int $quantity
    ) {
        $this->id = $id;
        $this->productId = $productId;
        $this->productName = $productName;
        $this->price = $price;
        $this->quantity = $quantity;
    }
    public function getSubtotal(): Money
    {
        return new Money($this->price->getAmount() * $this->quantity);
    }
    // Getters...
    public function getId(): string { return $this->id; }
    public function getProductId(): string { return $this->productId; }
    public function getProductName(): string { return $this->productName; }
    public function getPrice(): Money { return $this->price; }
    public function getQuantity(): int { return $this->quantity; }
}

值对象 - 订单状态

<?php
// Domain/ValueObject/OrderStatus.php
namespace App\Domain\ValueObject;
class OrderStatus
{
    public const PENDING = 'pending';
    public const PAID = 'paid';
    public const SHIPPED = 'shipped';
    public const CANCELLED = 'cancelled';
    private string $value;
    private const VALID_STATUSES = [
        self::PENDING,
        self::PAID,
        self::SHIPPED,
        self::CANCELLED,
    ];
    public function __construct(string $value)
    {
        if (!in_array($value, self::VALID_STATUSES)) {
            throw new \InvalidArgumentException('无效的订单状态');
        }
        $this->value = $value;
    }
    public function getValue(): string
    {
        return $this->value;
    }
    public function equals(OrderStatus $status): bool
    {
        return $this->value === $status->getValue();
    }
}

领域服务(Domain Services)

<?php
// Domain/Service/OrderPricingService.php
namespace App\Domain\Service;
use App\Domain\Entity\Order;
use App\Domain\ValueObject\Money;
class OrderPricingService
{
    private const DISCOUNT_THRESHOLD = 1000;
    private const DISCOUNT_RATE = 0.1; // 10% discount
    public function applyDiscount(Order $order): Money
    {
        $total = $order->getTotalAmount();
        if ($total->getAmount() >= self::DISCOUNT_THRESHOLD) {
            $discountedAmount = $total->getAmount() * (1 - self::DISCOUNT_RATE);
            return new Money($discountedAmount);
        }
        return $total;
    }
}

应用层(Application Layer)

应用服务(Application Services)

<?php
// Application/Service/OrderService.php
namespace App\Application\Service;
use App\Domain\Entity\Order;
use App\Domain\Entity\OrderItem;
use App\Domain\Repository\OrderRepositoryInterface;
use App\Domain\Repository\UserRepositoryInterface;
use App\Domain\ValueObject\Money;
use App\Application\DTO\CreateOrderRequest;
use App\Application\DTO\OrderResponse;
class OrderService
{
    private OrderRepositoryInterface $orderRepository;
    private UserRepositoryInterface $userRepository;
    public function __construct(
        OrderRepositoryInterface $orderRepository,
        UserRepositoryInterface $userRepository
    ) {
        $this->orderRepository = $orderRepository;
        $this->userRepository = $userRepository;
    }
    public function createOrder(CreateOrderRequest $request): OrderResponse
    {
        // 验证用户
        $user = $this->userRepository->findById($request->customerId);
        if (!$user) {
            throw new \DomainException('用户不存在');
        }
        // 创建订单实体
        $order = new Order(
            uniqid('order_', true),
            $request->customerId
        );
        // 添加订单项
        foreach ($request->items as $item) {
            $order->addItem(
                new OrderItem(
                    uniqid('item_', true),
                    $item['productId'],
                    $item['productName'],
                    new Money($item['price']),
                    $item['quantity']
                )
            );
        }
        // 保存订单
        $this->orderRepository->save($order);
        return OrderResponse::fromEntity($order);
    }
    public function getOrder(string $orderId): OrderResponse
    {
        $order = $this->orderRepository->findById($orderId);
        if (!$order) {
            throw new \DomainException('订单不存在');
        }
        return OrderResponse::fromEntity($order);
    }
    public function payOrder(string $orderId): OrderResponse
    {
        $order = $this->orderRepository->findById($orderId);
        if (!$order) {
            throw new \DomainException('订单不存在');
        }
        $order->pay();
        $this->orderRepository->save($order);
        return OrderResponse::fromEntity($order);
    }
}

DTOs(数据传输对象)

<?php
// Application/DTO/CreateOrderRequest.php
namespace App\Application\DTO;
class CreateOrderRequest
{
    public string $customerId;
    public array $items;
    public function __construct(string $customerId, array $items)
    {
        $this->customerId = $customerId;
        $this->items = $items;
    }
}
<?php
// Application/DTO/OrderResponse.php
namespace App\Application\DTO;
use App\Domain\Entity\Order;
use App\Domain\Entity\OrderItem;
class OrderResponse
{
    public string $id;
    public string $customerId;
    public array $items;
    public float $totalAmount;
    public string $status;
    public string $createdAt;
    public static function fromEntity(Order $order): self
    {
        $response = new self();
        $response->id = $order->getId();
        $response->customerId = $order->getCustomerId();
        $response->items = array_map(
            fn(OrderItem $item) => [
                'id' => $item->getId(),
                'productId' => $item->getProductId(),
                'productName' => $item->getProductName(),
                'price' => $item->getPrice()->getAmount(),
                'quantity' => $item->getQuantity(),
                'subtotal' => $item->getSubtotal()->getAmount()
            ],
            $order->getItems()
        );
        $response->totalAmount = $order->getTotalAmount()->getAmount();
        $response->status = $order->getStatus()->getValue();
        $response->createdAt = $order->getCreatedAt()->format('Y-m-d H:i:s');
        return $response;
    }
}

基础设施层(Infrastructure Layer)

仓储实现

<?php
// Infrastructure/Repository/InMemoryOrderRepository.php
namespace App\Infrastructure\Repository;
use App\Domain\Entity\Order;
use App\Domain\Repository\OrderRepositoryInterface;
class InMemoryOrderRepository implements OrderRepositoryInterface
{
    private array $orders = [];
    public function save(Order $order): void
    {
        $this->orders[$order->getId()] = $order;
    }
    public function findById(string $id): ?Order
    {
        return $this->orders[$id] ?? null;
    }
    public function delete(string $id): void
    {
        unset($this->orders[$id]);
    }
    public function findAll(): array
    {
        return array_values($this->orders);
    }
}

仓储接口

<?php
// Domain/Repository/OrderRepositoryInterface.php
namespace App\Domain\Repository;
use App\Domain\Entity\Order;
interface OrderRepositoryInterface
{
    public function save(Order $order): void;
    public function findById(string $id): ?Order;
    public function delete(string $id): void;
    public function findAll(): array;
}

使用示例

<?php
// index.php 或 Controller
use App\Application\Service\OrderService;
use App\Application\DTO\CreateOrderRequest;
use App\Infrastructure\Repository\InMemoryOrderRepository;
use App\Infrastructure\Repository\InMemoryUserRepository;
// 依赖注入设置
$orderRepository = new InMemoryOrderRepository();
$userRepository = new InMemoryUserRepository();
$orderService = new OrderService($orderRepository, $userRepository);
// 创建订单
$request = new CreateOrderRequest('user123', [
    [
        'productId' => 'prod1',
        'productName' => 'iPhone',
        'price' => 5000,
        'quantity' => 1
    ],
    [
        'productId' => 'prod2', 
        'productName' => 'AirPods',
        'price' => 1500,
        'quantity' => 2
    ]
]);
try {
    $orderResponse = $orderService->createOrder($request);
    echo "订单创建成功: " . $orderResponse->id . "\n";
    echo "总金额: " . $orderResponse->totalAmount . "\n";
    // 支付订单
    $orderResponse = $orderService->payOrder($orderResponse->id);
    echo "订单支付成功,状态: " . $orderResponse->status . "\n";
} catch (\Exception $e) {
    echo "错误: " . $e->getMessage() . "\n";
}

目录结构

project/
├── src/
│   ├── Domain/
│   │   ├── Entity/
│   │   │   ├── Order.php
│   │   │   └── OrderItem.php
│   │   ├── ValueObject/
│   │   │   ├── Money.php
│   │   │   └── OrderStatus.php
│   │   ├── Service/
│   │   │   └── OrderPricingService.php
│   │   └── Repository/
│   │       ├── OrderRepositoryInterface.php
│   │       └── UserRepositoryInterface.php
│   ├── Application/
│   │   ├── Service/
│   │   │   └── OrderService.php
│   │   └── DTO/
│   │       ├── CreateOrderRequest.php
│   │       └── OrderResponse.php
│   └── Infrastructure/
│       ├── Repository/
│       │   ├── InMemoryOrderRepository.php
│       │   └── InMemoryUserRepository.php
│       └── Database/
│           └── (数据库相关类)
└── index.php

这个示例展示了DDD的核心概念:

  • 值对象:Money、OrderStatus
  • 实体:Order、OrderItem
  • 领域服务:OrderPricingService
  • 应用服务:OrderService
  • 仓储接口与实现:OrderRepositoryInterface
  • DTO:CreateOrderRequest、OrderResponse

抱歉,评论功能暂时关闭!