“文件夹只是建议,没有阻止导入。”大概每个读完六边形架构文章的 PHP 开发者,都会经历这样一次幻灭:你对着那张漂亮的六边形图画出 Domain、Application、Infrastructure 三个文件夹,心里已经把自己归类到架构整洁派了。可两周之后,一个 use Doctrine\ORM\EntityManagerInterface 赫然坐在某个领域实体的文件顶部,并且没人记得是谁批的。你以为有了三层文件夹就防住了腐化,但编写代码时根本没有东西替你挡住那只伸向内层的手。
这篇文章就给你一套硬梆梆的规矩——不是观念,是能直接落到 composer.json、目录树和 CI 流水线里的东西。目标运行环境是 PHP 8.4+,搭配标准的 PSR-4 自动加载,但思路对所有版本都成立。
![]()
先看目录。整个 src/ 底下只有三个顶级命名空间,和磁盘上的三个目录严丝合缝地对应:
src/Domain/ ——这是纯 PHP 的领地,连一行 vendor 里的 import 都不该出现。里面按业务拆分子目录,比如 Order/Order.php、Order/OrderId.php、Order/OrderStatus.php,还有 Customer/ 和像 Shared/Money.php 这样的横切值对象。
src/Application/ ——用例和端口呆的地方。 Order/PlaceOrder.php 和 PlaceOrderInput.php 表达了“下订单”这件事,而 Port/OrderRepository.php、Port/PaymentGateway.php、Port/Clock.php 则是用例们对外提要求的接口。
src/Infrastructure/ ——这才是真正与外界打交道的一层。框架的控制器、Doctrine 的持久化实现、Stripe 支付适配器、系统时钟的封装,以及装配一切的引导容器,全部塞在这里。 Persistence/Doctrine/、Http/Controller/、Payment/Stripe/、Clock/SystemClock.php 和 Bootstrap/Container.php 各自归位。
这三层就是一个同心环,Domain 是圆心,Infrastructure 是接触真实世界的外缘,Application 夹在中间,装着用例和用例所依赖的接口(端口)。
目录定下来之后,下一步是让命名空间把架构讲清楚。 composer.json 里只保留一行 PSR-4 声明:"App\\": "src/" 。这意味着 src/Domain/Order/Order.php 的完整类名就是 App\Domain\Order\Order 。 App\ 之后的第一段立刻告诉你它属于哪个层,连脑内解码的时间都省了。那种把各种概念拍平在根命名空间下的做法——比如 App\Models、App\Services、App\Http——恰恰抹掉了层的承重作用。在六边形架构里,层是第一优先级的信息,所以它必须出现在最前面。同理,也请别把框架自带的 App\Controller 或 App\Http 约定搬进来,它们习惯把所有东西揉成一个袋子,而你要做的恰恰相反。
有了目录和命名空间,还得有导入方向这个“门禁”。规则就是一句话:导入永远指向内层,绝不向外。想象一下套娃,外头看得见里头,里头不知道外头的存在。
具体到这三个层,Domain 是最内圈,只能导入自身的类。任何朝向 vendor、甚至朝向 Application 的 import 都算犯规。Application 是中间层,可以导入 Domain 和自己,但正常情况下决不允许拉进 vendor 里的东西——只有一个公开的特例:PSR 接口(比如 Psr\Log\LoggerInterface、Psr\Clock\ClockInterface)以及纯库的价值类型,是被放行的。原文只点到这几个名字,你按同样的思路去判断其他候选即可。最外头的 Infrastructrue 没有限制,它本就该导入所有层,因为它的全部工作就是在外部世界和内部腔体之间当翻译。
读到这里你可能已经感觉到了,这套规则单靠人工 code review 是守不住的,一定会被时间磨没。所以文章还给出了一条最后的防线:在 CI 阶段加一个检查,一旦有人让 import 指错了方向,构建就直接挂掉。具体用什么工具实现不是这里的重点,但你只要知道,边界执行的严肃程度已经可以提到“不通过就进不了仓库”这个档次了。
把目录建好只是给你在地面上画了几条线,导入规则和自动化检查才是真正砌起来的墙。下次当那个 use Doctrine 再次出现在 Domain 目录的时候,你至少能够理直气壮地说:不是“建议”,而是“禁止”。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.