PHP类型声明是运行时强制校验的契约,需严格遵循语法与规则:参数必须带变量名,strict_types=1须为文件首行,?string不可写作string|null,callable不能用于属性,iterable不可加?前缀。

PHP类型声明不是“可选装饰”,而是运行时强制校验的契约——写错位置、漏掉declare(strict_types=1)、或混淆?string和string|null,都会在调用时直接抛出TypeError。
函数参数类型声明必须带变量名,不能只写类名
常见错误是把类型当语法糖省略变量,比如写成function handle(User) { }——这会报Parse error: syntax error。PHP要求每个参数必须有显式变量名。
- 正确写法:
function handle(User $user): void { echo $user->getName(); } - 传入非
User实例(如new Admin())时是否允许?取决于继承关系:只要Admin是User子类或实现同一接口,就合法 - 标量类型(
int、string等)在弱模式下会尝试转换,比如function foo(int $x) { }传入"123"能过;但开启declare(strict_types=1)后,"123"直接触发TypeError
返回值类型声明冒号后不能空格,且void不接受return值
function now(): int合法,function now() : int(冒号前有空格)在PHP 8.0+中会被解析为返回类型: int,但实际运行时报Parse error——因为PHP解析器把空格后的int当成了函数体的一部分。
-
void表示“不返回任何东西”,写了就不能return "done",只能return;或不写return - 如果函数有多个分支,所有分支都必须满足返回类型,比如
function find(int $id): ?string,找不到时必须return null,不能漏掉return - 返回类型不受
strict_types影响,它始终严格:声明: string却return 123,无论是否开启严格模式,都抛TypeError
属性类型声明从PHP 7.4起支持,但callable不能用于属性
类属性声明类型看起来简单,但几个关键限制常被忽略:
立即学习“PHP免费学习笔记(深入)”;
-
public callable $callback;是语法错误——callable只允许用于函数参数,不能用于属性或返回值 - 可空类型必须用
?string,而不是string|null;后者在PHP里是无效语法,会报Parse error - 属性初始化必须匹配类型:
public int $count = "1";在严格模式下直接失败,即使构造函数里再赋值也救不回来——声明时的默认值就得合规 -
iterable可接受array或任何Traversable对象,比array更灵活,但注意它不能用?前缀(?iterable非法)
strict_types=1只作用于当前文件,且必须是第一条语句
很多人把declare(strict_types=1)放在namespace之后、或注释下面,结果整个文件还是弱模式——它必须紧接<?php 之后,前面不能有任何输出、空行或BOM。
- 跨文件调用时,调用方的
strict_types设置不影响被调用函数的行为:函数自身的文件是否启用严格模式,才决定它的参数校验逻辑 - 第三方库没开严格模式,你的代码开了也没用——类型校验边界在函数定义处,不在调用处
- 想全局启用?不行。每个文件独立控制。建议新项目统一在所有PHP文件顶部加这一行,老项目迁移时逐个验证
最容易被忽略的是:类型声明一旦加上,就不再是开发期提示,而是运行时硬约束。哪怕只是function log(string $msg),传null进去就是TypeError,没有商量余地——这时候你要么改声明为?string,要么在调用前做is_string()判断,别指望自动兜底。



















