PHP参数类型声明参与运行时校验,strict_types=1需显式声明于文件首行(无任何前置内容),否则退化为弱类型隐式转换。

PHP参数类型声明不是“加个注释就完事”,它直接参与运行时校验,开 strict_types=1 后传错类型立刻报 TypeError;不开则可能隐式转换,埋下逻辑隐患。
strict_types=1 必须显式声明才生效
它只对当前文件有效,且必须写在文件最顶部(前面不能有任何输出、空行、BOM 或注释)。漏掉或位置不对,类型声明就退化成弱模式:
-
declare(strict_types=1);—— 正确,整份文件启用严格校验 <?php declare(strict_types=1);—— 正确(<?php是合法起始)-
// 注释\ndeclare(strict_types=1);—— ❌ 失效,因前面有内容 -
declare(strict_types=1); echo "hello";—— ❌ 失效,因后面紧跟非声明语句(PHP 会忽略后续所有声明)
弱模式下,int $x 接收 "123" 会被转成 123;严格模式下直接抛出 TypeError: Argument 1 passed to foo() must be of the type int, string given。
参数类型写法必须紧挨变量名前
PHP 8+ 要求标量、类、接口、联合类型等全部写在参数变量名之前,顺序错一个字符就报 Parse error: syntax error, unexpected token ":":
立即学习“PHP免费学习笔记(深入)”;
-
public function setPrice(float $price): void—— ✅ 正确 -
public function setPrice($price: float)—— ❌ PHP 不认这种“后置冒号”写法(那是 TypeScript) -
public function setPrice(float($price))—— ❌ 语法错误,括号不能包类型 -
public function setPrice($price): float—— ❌ 这是返回值类型,不是参数类型
可空类型同理:?string $desc = null 是唯一安全组合;string $desc = null 在 strict 模式下必炸。
可空类型与默认值的搭配规则
可空不是“加个问号就万事大吉”,它和默认值必须语义一致,否则运行时报错:
-
?int $id = null—— ✅ 明确允许 null,且默认值匹配 -
string $name = ''—— ✅ 非空类型配非空默认值 -
?string $name = 'default'—— ⚠️ 警告:类型声明允许 null,但默认值不是 null,调用时若不传参会得到'default',逻辑上没问题,但易误导协作者 -
int $count = null—— ❌ 严格模式下直接拒绝解析:类型不匹配
注意:null 本身不是类型,?T 才是“T 或 null”的联合类型。所以 mixed 或 array|null(PHP 8.0+)这类写法要慎用,IDE 和静态分析工具支持度不一。
对象类型声明不是继承,而是契约
写 User $user 并不意味着你要继承 User 类,而是要求传入的必须是 User 实例(或其子类、实现相同接口的类):
-
function process(User $u): void { echo $u->getName(); }—— ✅ 安全调用 public 方法 -
process(new Guest())—— ✅ 若Guest extends User,合法 -
process("not an object")—— ❌ 严格模式下报TypeError -
process(null)—— ❌ 即使没开 strict,也会报TypeError(对象类型默认不可空,除非显式写?User)
最容易被忽略的是:类型声明只校验“是不是这个类的实例”,不校验对象状态(比如是否已初始化、属性是否为空)。该做的空值判断、业务校验,仍需手动写。



















