测试:停止甩锅给语言的最快方式

📅 2026/6/30 1:57:16
测试:停止甩锅给语言的最快方式
很多 PHP 团队不写测试因为早年写起来确实别扭。但现在的 PHP 写测试已经很顺手了。下面用一个简单的 PHPUnit 例子演示通过 mock 仓储测试业务逻辑完全不需要数据库。✅ PHPUnit 风格的单元测试无需数据库?php declare(strict_types1); use PHPUnit\Framework\TestCase; final class PlaceOrderHandlerTest extends TestCase { public function test_it_places_an_order_and_returns_total(): void { $tx new class implements TransactionManager { public function run(callable $fn): mixed { return $fn(); } }; $users new class implements UserRepository { public function getStatus(int $userId): ?string { return active; } }; $products new class implements ProductRepository { private array $stock [10 5]; public function getSnapshot(int $productId): ?ProductSnapshot { if ($productId ! 10) return null; return new ProductSnapshot(10, price: 200, stock: $this-stock[10]); } public function decreaseStock(int $productId, int $qty): void { $this-stock[$productId] - $qty; } }; $orders new class implements OrderRepository { public function create(int $userId, int $total, array $lines): int { return 123; } }; $handler new PlaceOrderHandler($tx, $users, $products, $orders); $cmd new PlaceOrderCommand( userId: 7, items: [ [productId 10, qty 2], ] ); $result $handler-handle($cmd); $this-assertSame(123, $result-orderId); $this-assertSame(400, $result-total); } }如果你的用例能这样测试PHP 不可维护这种话就很难再理直气壮地说出口了。可维护性不是语言自带的能力是靠结构和测试撑起来的。框架神话Laravel/Symfony 不会自动拯救你框架有用但它拦不住你写出烂架构。比如在 Laravel 里你照样可以写出臃肿的控制器把领域逻辑全塞进 Eloquent 模型因为觉得绕了一层而直接跳过服务层如果你见过控制器写了 800 行的 Laravel 项目问题不在 Laravel而在于团队把框架当成了不做设计的理由。框架是工具箱。它能盖房子——也能堆一堆木头。为什么 PHP 比其他技术栈更容易挨骂原因说起来有点微妙在 PHP 里糟糕的决策暴露得更快。有些技术栈的抽象层能把烂代码盖住更长时间。但在 PHP 里写得烂一眼就能看出来职责混杂约定不一致复制粘贴的重复代码隐蔽的全局变量随意的错误处理PHP 不会替你兜底所以它最容易被拎出来当靶子。但一门逼你守规矩的语言不见得更好它只是让你更难偷懒。PHP 把门槛放得很低——所以你的团队文化反而更重要。整洁的 PHP很无聊——这是夸奖写得整洁的 PHP 代码通常看起来平平无奇命名清晰函数短小输入输出明确错误处理可预测依赖注入尽量少的魔法它不炫技不追求巧妙。无聊的代码在凌晨两点容易调试。无聊的代码容易交给新同事。无聊的代码在团队扩张时能扛得住。如果你希望 PHP 不再被当笑话那就写无聊的 PHP。实操清单如何停止写被人骂的 PHP如果你想写出不被人嘲笑的 PHP 系统下面是一份实用的底线清单在新代码中开启严格类型declare(strict_types1);所有依赖通过 Composer 和自动加载管理不要手动 include。保持控制器轻薄只处理 HTTP业务规则放到 handler/service 中。领域规则和持久化分离仓储或查询服务能保持数据访问的一致性。使用显式的 DTO 传递请求和命令不要到处传裸数组。区分领域错误和系统错误不是每个异常都该是 500。在用例层添加单元测试如果业务逻辑离了数据库就没法测说明你的边界划错了。使用静态分析工具PHPStan/Psalm防止隐性回归。引入代码风格工具并在 CI 中强制执行一致性很重要。持续重构如果重构变成了一个项目那它永远不会发生。以上这些不是 PHP 独有的——恰恰相反放到哪个语言都一样。结语PHP 是一面镜子——别砸镜子