PHP静态变量跨调用持久化问题及解决方案咨询
问题根源:静态变量的类级共享特性
你遇到的问题核心在于静态变量是属于整个类的,而不是类的某个实例——不管你创建多少个foo实例,所有实例和静态方法操作的都是同一个$a变量,它的值会在类的生命周期内一直保留,直到脚本结束或者手动重置。
一步步拆解你的代码执行过程:
- 第一次
foo::print():此时类的静态$a初始值是#,所以输出#,符合预期。 foo::more('foo')->more('foo')->print():- 第一个
foo::more('foo'):调用静态方法more,直接修改类的$a为#foo,然后返回一个新的foo实例。 - 接着调用这个实例的
more('foo'):注意,即使通过实例调用静态方法,PHP仍然会指向类的静态方法,所以还是修改了同一个类的$a,变成#foofoo,再返回新实例。 - 最后调用
print(),输出当前类的$a值#foofoo,这部分你理解的没错。
- 第一个
foo::more('foo')->print():- 此时类的
$a已经是#foofoo了,调用more('foo')会再次给它追加foo,变成#foofoofoo,所以print()输出这个值——这就是第三行出现3个foo的原因。
- 此时类的
你的误区在于:以为链式调用返回的新实例会拥有独立的$a,但$a是静态属性,它不属于任何实例,只属于foo类本身,所有操作都会共享同一个值。
解决方法:用实例属性替代静态属性
如果想要每次链式调用都拥有独立的上下文(也就是每次调用都是独立的“链条”,互不干扰),应该把$a改成实例属性,同时调整方法为实例方法(或者保留静态方法作为实例入口):
class foo { private $a = '#'; // 改为实例属性,每个实例都有自己的$a // 静态方法作为创建实例的入口,初始化第一个追加值 public static function more($string) { $instance = new static(); $instance->a .= $string; return $instance; } // 实例方法,用于后续链式追加 public function add($string) { $this->a .= $string; return $this; } public function print() { echo $this->a . "\n"; } } // 现在的调用效果: foo::more('foo')->print(); // 输出 #foo foo::more('foo')->add('foo')->print(); // 输出 #foofoo foo::more('foo')->print(); // 输出 #foo(和第一次调用互不干扰)
这样每个foo实例都拥有自己独立的$a属性,不同的链式调用链条之间就不会互相影响了。
内容的提问来源于stack exchange,提问作者Michael Arrison
相关产品推荐
相关产品推荐

