会。静态属性属于类本身,所有实例共享同一内存地址,修改后其他实例立即可见;不可用$this访问,需用类名或self/static;::支持后期静态绑定,self::编译时绑定;多进程下无锁易竞态;Web中生命周期仅为单请求,跨请求需用Redis等外部存储。

会。用 :: 修改类的静态属性,所有实例共享该值,因为静态属性属于类本身,而非某个对象实例。
静态属性在内存中只有一份副本
PHP 中 static 属性不随 new 实例化而复制,它被分配在类的符号表中,所有实例通过类名或 self/static 访问的都是同一块内存地址。
常见错误现象:修改一个实例通过 self::$prop 赋值后,另一个新创建的实例读取该属性发现值已变——这不是“污染”,而是设计如此。
- 使用场景:计数器、配置缓存、连接池单例标识等需要跨实例同步的状态
- 注意:不能用
$this->访问静态属性,否则报Access to undeclared static property - 若需每个实例隔离状态,请改用普通属性 + 构造函数初始化
:: 和 self:: 的行为差异
表面上都用于访问静态成员,但绑定时机不同::: 是运行时解析(支持后期静态绑定),self:: 是编译时绑定(永远指向定义它的类)。
立即学习“PHP免费学习笔记(深入)”;
class A {
public static $name = 'A';
}
class B extends A {
public static function getName() {
return self::$name; // 永远返回 'A'
// return static::$name; // 若取消注释,则返回子类重写的值(如 B 重写了 $name)
}
}所以用 A::$name = 'changed' 或 B::$name = 'changed' 都会直接改写对应类声明的静态属性;而 self:: 在 A 里写死,就不可能访问到 B 的同名静态属性,哪怕 B 继承了它。
修改静态属性前必须确认是否允许多处写入
没有内置锁机制,多线程(如 PHP-FPM 多进程)下并发修改会导致竞态。例如:
- 用
static::$counter++做请求计数,可能漏计(两个进程同时读 100,各自加 1 再写回 101) - Web 环境中静态属性生命周期=单个请求周期,FPM 下每次请求都会重置,不要误以为能跨请求持久化
- CLI 模式下若长时运行(如守护进程),静态属性才真正“长期存在”,此时更需注意初始化和清理
如果需要跨请求共享且可写,应改用 Redis、APCu 或数据库,而不是依赖静态属性。
最易忽略的一点:static 属性的初始化表达式只能是常量或字面量,不能是函数调用或变量——PHP 解析期就要求确定值,这点和 Java/C# 不同。











