不能将所有工具函数塞进一个Utils类,因其导致三类硬伤:命名空间混淆引发误用、静态变量在多线程/Swoole下状态污染、无法注入依赖违背单一职责。

直接用 static 方法堆砌工具类,短期爽,长期容易失控——方法之间隐式耦合、错误处理不统一、测试难覆盖、配置无法隔离。
为什么不能把所有工具函数塞进一个 Utils 类里?
看似省事,实则埋下三类硬伤:
- 所有方法共享同一个命名空间,
str2date()和date2str()这类易混淆名一旦散落在不同业务模块里,调用时极易传反参数或误用上下文 - 没有实例状态管理能力,比如 HTTP 工具需要复用
cURL句柄、数据库工具需要缓存连接配置,全靠静态变量撑着,多线程/协程环境下会出错 - 无法按需注入依赖(如日志器、重试策略、超时配置),每个方法都得自己 new 一遍,违背单一职责
HttpTool 类该不该带构造函数?
应该带,而且默认构造函数要留出配置入口。不带构造函数的纯静态类,等于放弃控制权。
- 必须支持传入基础配置:
timeout、base_uri、headers、verify_ssl - 推荐用数组或配置对象初始化,避免构造函数参数爆炸,例如:
new HttpTool(['timeout' => 5, 'verify_ssl' => false]) - 如果项目已用 DI 容器,构造函数应接受接口类型(如
LoggerInterface),而不是具体实现 - 禁止在构造函数里执行实际请求——那是
get()/post()的事,不是初始化的事
怎么处理工具类里的“伪全局”配置?
别用 self::$config 或 static::$defaultHeaders。这类静态属性在 CLI 命令、FPM 请求、Swoole Worker 之间会互相污染。
立即学习“PHP免费学习笔记(深入)”;
- 把配置固化在实例上,每个
HttpTool实例只管自己的配置 - 如需跨实例共享默认值,用独立的
ConfigProvider类,通过单例 + 显式调用获取,而不是让工具类自己去读 - 敏感配置(如 API key)绝不能写死在类里,必须由外部传入,或从环境变量/配置中心加载后显式 set
- 若真要用静态默认值,至少加个
resetDefaults()方法供测试清理,否则单元测试会串扰
封装时最容易被忽略的边界点
不是语法,是生命周期和错误归因。
- HTTP 工具类返回
null还是抛异常?统一选后者。空响应、超时、4xx/5xx 都该转成明确异常(如HttpRequestException),让调用方决定兜底逻辑 - 日期格式化工具遇到非法时间字符串,是返回 false 还是 throw?PHP 本身
DateTime构造失败就 throw,工具类应保持一致语义 - 所有对外方法必须声明返回类型(PHP 7.4+),
public function get(string $url): array比public function get($url)更可靠——类型即契约 - 不要为“方便”暴露
__callStatic或魔术方法,那会让 IDE 失效、静态分析失效、重构变地狱



















