联合类型使工厂方法的返回值和参数声明更精确:返回值必须是明确枚举的类型之一(如user|admin|guest),参数可限定为字面量或枚举(如'file'|'database'),并强制处理null等边界情况,提升类型安全与可维护性。

联合类型让工厂方法的返回值声明更精确
简单工厂的核心问题是:调用方无法从签名上确认返回的是什么。以前写 createUser(),返回值只能标 object 或干脆不标,IDE 推不出方法、静态分析拦不住误用。PHP 8 的联合类型允许你明确写出 function createUser(string $type): User|Admin|Guest——不是“可能返回其中之一”,而是“必须返回这三者之一”,且运行时会强制校验。
常见错误现象:调用方把 createUser('admin') 的结果当 User 用,调了 User 有但 Admin 没有的方法,直到运行时报错;现在 PHP 解析器在编译期就能报 Call to undefined method Admin::getProfileUrl()(如果该方法只在 User 中定义)。
- 返回类型必须覆盖所有分支路径,漏写一个分支(比如忘了
'guest')会导致类型不匹配错误 - 不能用
mixed或object混过去——联合类型不接受模糊类型作为成员 - 如果工厂逻辑里某条路径意外返回了
null,而声明里没写|null,就会触发致命错误,逼你显式处理空值场景
参数类型收窄让工厂入参更可控
工厂方法接收的标识符(如角色名、配置键、数据源类型)常是字符串字面量,但传统 string 声明太宽泛,容易传错值。联合类型配合字面量类型(PHP 8.2+)或枚举(PHP 8.1+)能收紧入口:
例如:function createLogger(string $driver): FileLogger|DatabaseLogger|NullLogger 看似合理,但 $driver 可能被传成任意字符串。升级为 function createLogger('file'|'database'|'null' $driver): ... 后,传 'redis' 直接编译失败。
- 若尚未升级到 PHP 8.2,可用
enum LoggerDriver: string { case file = 'file'; case database = 'database'; }替代,参数声明为LoggerDriver $driver - 避免在工厂内部做
if ($driver === 'file')类型路由——那属于策略模式职责;联合类型 + 枚举让类型系统替你守门 - 参数联合类型和返回联合类型要语义对齐:输入
'file'就该对应返回FileLogger,否则 IDE 和 psalm/phpstan 会警告类型不一致
与可空类型协同暴露工厂的边界条件
工厂不是万能的。当输入非法、配置缺失、依赖未注册时,它理应失败,而不是硬塞个半成品对象。联合类型天然支持 |null,配合 ?Type 语法,能清晰表达“成功返回具体类型,失败返回 null”这一契约。
例如:function findConnection(string $name): MysqlConnection|PostgresConnection|null 比返回 ConnectionInterface 更诚实——它告诉你:“找不到就真没有,别幻想兜底”。调用方必须处理 null,而不是盲目调用 ->query()。
- 不要写
function createService(string $id): Service|null这种过度宽泛的联合——失去类型提示价值;应具体到可能的实现类 -
?Service等价于Service|null,但仅当Service是单一类型时才允许;若你写?MysqlConnection|PostgresConnection,PHP 会报错:可空修饰符不能用于联合类型 - 工厂方法里用
return null;必须和声明完全匹配;返回new class extends Service {}会因类型不兼容而失败,倒逼你提前定义好所有合法产出类型
注意:联合类型不解决工厂逻辑本身的缺陷
类型再严,也防不住工厂内部写错分支。比如声明返回 User|Admin,但代码里把 'admin' 分支写成了 new User(),PHP 不会报错——因为 User 是联合成员之一。真正起作用的是类型+逻辑的一致性,这得靠测试和代码审查来补位。
最容易被忽略的一点:联合类型声明本身会成为工厂的隐式契约文档。一旦新增一种产品类型,你不仅要加创建逻辑,还必须改返回类型声明。这个“改声明”的动作,会强制你检查所有调用方是否适配新类型——比靠人肉 grep 可靠得多。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











