PHP中的领域驱动设计:如何避免陷入复杂性

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

PHP中的领域驱动设计:如何将混乱变为有序

\n\n

你是否曾感觉自己的PHP项目像雪球一样越滚越大?一开始一切都很简单:几个控制器、一个模型、几次数据库查询。但半年后,你陷入了意大利面条式代码,业务逻辑分散在各个服务中,一个“简单”的需求变更就要花费一周时间。

\n\n

熟悉吗?欢迎加入这个俱乐部。但好消息是:领域驱动设计(DDD)——并非Eric Evans厚书中的抽象理论。它是一个实用的工具,能真正帮助你编写对业务和开发人员都易于理解的PHP代码。

\n\n

在本文中,我们将结合实际案例,深入探讨DDD的实践应用。没有废话,只有PHP的鲜活示例。你将了解如何在不伤脑筋、不重写所有代码的情况下,将DDD引入你的项目。开始吧!

\n\n

什么是领域驱动设计,PHP开发者为何需要它?

\n\n

想象一下,你正在编写一个在线商店。有折扣、购物车、订单。业务逻辑是:“折扣不与优惠码叠加”、“订单发货后不可取消”。如果你将这些逻辑存储在控制器中或分散在ORM模型中,迟早会陷入混乱。

\n\n

DDD是一种将业务领域(你的问题域)置于开发核心的方法。与其考虑表和SQL查询,不如思考实体、值和事件。

\n\n

这对PHP尤为重要。这门语言很灵活,但如果没有清晰的架构,项目很快就会变成“遗留系统”。DDD提供了一个框架,即使一年后代码依然可读。

\n\n

战略设计 vs 战术设计

\n\n

DDD分为两大部分:

\n
    \n
  • 战略设计——项目的蓝图。你识别出限界上下文,构建通用语言。例如,在“目录”上下文中,商品只是一组属性;而在“订单”上下文中,它是一个带有价格和数量的单位。
  • \n
  • 战术设计——构建块:实体、值对象、聚合、仓库、领域服务、领域事件。我们将重点关注这些。
  • \n
\n\n

PHP中的战术设计:DDD的构建块

\n\n

让我们看看DDD的主要模式在PHP中是如何呈现的。忘掉Laravel或Symfony中的ActiveRecord——这里我们构建一个独立于框架的模型。

\n\n

1. 实体

\n

实体是一个具有唯一标识符且随时间变化的对象。例如,User或Order。实体通过ID进行比较,而非字段。

\n\n
<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Domain\\Entity;\n\nuse App\\Domain\\ValueObject\\UserId;\nuse App\\Domain\\ValueObject\\Email;\n\nclass User\n{\n    public function __construct(\n        private UserId $id,\n        private string $name,\n        private Email $email\n    ) {}\n\n    public function getId(): UserId\n    {\n        return $this->id;\n    }\n\n    public function changeEmail(Email $newEmail): void\n    {\n        // 这里可以包含业务逻辑:检查邮箱是否已被占用\n        $this->email = $newEmail;\n    }\n\n    public function getEmail(): Email\n    {\n        return $this->email;\n    }\n}\n
\n\n

2. 值对象

\n

值对象是一个不可变对象,由其属性而非标识符定义。两个值对象如果所有字段都相同,则相等。经典例子:Money、Email、Address。

\n\n
<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Domain\\ValueObject;\n\nclass Email\n{\n    private string $value;\n\n    public function __construct(string $value)\n    {\n        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {\n            throw new \\InvalidArgumentException('Invalid email address');\n        }\n        $thi                

博客

书籍推荐