PHP 8.1+ 中给 int 类型属性赋字符串值会触发致命错误“Cannot assign string to property of type int”,因属性类型声明强制校验,需用 filter_var($id, FILTER_VALIDATE_INT) 安全转换并校验。

PHP 8.1+ 强制类型声明下,给 int 类型属性赋字符串值会直接报错:Cannot assign string to property of type int。这不是警告,是致命错误,代码会中断执行。
为什么会出现这个错误
你定义了一个类属性,显式声明为 int 类型(比如 public int $id;),但在初始化或后续赋值时传入了字符串(如 '123'、$_GET['id'] 或 JSON 解析出的字符串数字)。PHP 8.1+ 不再自动转换,拒绝隐式类型 coercion。
- 常见于从 URL 参数、表单提交、JSON 请求体、数据库原始结果(PDO 默认返回字符串)中读取数字字段
- 也容易在反序列化或调用第三方 API 后未做类型校验时触发
- 注意:即使字符串内容是纯数字(如
'42'),也不会被接受
修复方法:显式转换 + 提前校验
不能依赖自动转换,必须手动转并确保安全。推荐组合使用 filter_var() 或强制类型转换,但要注意边界情况:
- 用
(int)转换最简捷,但会静默截断('123abc'→123),不适合校验场景 - 用
filter_var($val, FILTER_VALIDATE_INT)更严格,失败返回false,可配合默认值或异常处理 - 如果来源可控(如已知是数字字符串),
intval($val)或+$val也可用,但不校验有效性 - 别在构造函数里直接写
$this->id = $_GET['id'];—— 必须先处理
示例修复:
立即学习“PHP免费学习笔记(深入)”;
class User {
public int $id;
public function __construct(string|int $id) {
// 安全转换:校验是否为合法整数
$intId = filter_var($id, FILTER_VALIDATE_INT);
if ($intId === false) {
throw new InvalidArgumentException('Invalid ID: must be an integer');
}
$this->id = $intId;
}
}
兼容旧代码的临时方案(不推荐长期使用)
如果你正在升级 PHP 版本且暂时无法全面改造模型层,可考虑以下折中方式,但会掩盖真实问题:
- 将属性类型改为
int|string联合类型(PHP 8.0+),后续逐步收敛 - 在 setter 中做转换:
public function setId(string|int $id): void { $this->id = (int)$id; },但需确保业务逻辑能容忍截断 - 禁用严格模式?不行 ——
declare(strict_types=0)对属性类型声明无效,该错误不受此控制
注意:settype($var, 'integer') 和 is_numeric() 都不能替代 FILTER_VALIDATE_INT,前者不返回布尔结果,后者会把 '1e3' 或 '0x1A' 当作合法数字。
真正棘手的是那些藏在深层嵌套数组或动态属性赋值里的字符串数字 —— 它们不会立刻报错,直到某个对象实际尝试写入 int 属性时才崩。上线前务必用真实请求路径覆盖所有数据入口点。



















