php 8.0+ 要求类属性必须显式声明 public/protected/private,否则报 parseerror;static 属性需用 self:: 访问;php 8.2+ readonly 属性须在构造函数初始化且不可变;类型声明在严格模式下强制校验。

PHP类属性声明必须加访问修饰符
PHP 8.0+ 已彻底禁止不带 public、protected 或 private 的属性声明,写 class A { $name; } 会直接报 ParseError: Syntax error。这不是警告,是解析失败,代码根本跑不起来。
常见错误现象:从 PHP 7.x 升级后突然报错,或者在 IDE 里没报错但运行时挂掉——大概率是漏写了修饰符,或误用了老式写法(比如用 var)。
-
var是 PHP 4 遗留语法,PHP 5.0 起已废弃,PHP 7.4+ 完全移除,现在用会直接报错 - 不写任何修饰符 ≠ 默认 public;它等于语法错误,PHP 解析器根本不认识这种写法
- 如果想兼容旧代码迁移,别试图绕过修饰符,老老实实补上
public
static 属性必须显式声明,且不能和 $this 混用
静态属性属于类本身,不是实例,所以声明时必须带 static 关键字,且访问时不能通过 $this->,否则报 Fatal error: Uncaught Error: Using $this when not in object context。
使用场景:配置项缓存、单例实例、计数器等跨实例共享的数据。
立即学习“PHP免费学习笔记(深入)”;
- 声明格式只能是:
public static $count = 0;或private static $instance; - 读取时用
self::$count或static::$count,写入同理;$this->$count一定错 - PHP 8.1+ 支持只读静态属性:
public static readonly string $VERSION = '1.0';,但一旦赋值就不能改
PHP 8.2+ 支持只读属性(readonly),但有硬性限制
只读属性只能在构造函数中赋值一次,之后不可修改,连反射都不能绕过。但它不是“常量”,而是实例级只读,适合封装不可变状态。
容易踩的坑:很多人以为 readonly 只是语义提示,实际是运行时强约束;一旦漏写构造函数赋值,或重复赋值,立刻报 Fatal error。
- 声明格式:
public readonly string $id;,必须搭配构造函数初始化 - 只读属性不能是
static,也不能是array类型(PHP 8.2 不支持,8.3 才放开) - 如果属性是对象,只读保护的是引用本身,不递归保护对象内部属性
- 用
isset($obj->id)判断是否已初始化,未初始化时返回false
类型声明不是可选项,尤其在严格模式下
PHP 7.4+ 支持属性类型声明,但不写类型 ≠ “灵活”,而是放弃类型安全。开启 declare(strict_types=1); 后,传入错误类型不会自动转换,直接报 TypeError。
性能影响其实很小,但能提前暴露问题。比如 public int $age; 声明后,传字符串 "25" 就会崩,而不是默默转成 25。
- 支持的类型包括:
string、int、bool、float、array、object、类名、联合类型(如string|int) - 可空类型必须写成
?string,不能写string|null - 没有默认值的非空类型属性,必须在构造函数里赋值,否则实例化时报
Uninitialized property
static、类型写错位置,都可能让错误出现在运行时而非编辑期——而这恰恰是最难排查的。











