一个类中的静态属性由另一个类设置


Static properties in one class set by another

我一直在PHP 5.3.x中开发一组遵循活动记录模式的小类。然而,在处理静态属性时,我遇到了一个问题。以下是我一直在测试的代码:

<?php
class dbPreparedObject {
    public static $insert = "";
    public function __construct() {
        static::$insert = "autoinsert_".get_called_class();
    }
}
class gtRecord extends dbPreparedObject {}
class nRecord extends dbPreparedObject {}
$a = new gtRecord();
$b = new nRecord();
var_dump(gtRecord::$insert);
var_dump(nRecord::$insert);

输出:

string(18) "autoinsert_nRecord"
string(18) "autoinsert_nRecord"

I、 期望第一个字符串读取autoinsert_gtRecord

似乎没有被子类实例化的静态属性被绑定在一起了。有没有任何方法可以在不在每个子类中声明public static $insert = ""的情况下将它们分离?

这是预期的行为。在PHP中,声明为静态的属性在创建的对象的所有实例之间共享。也就是说,在dbPreparedObject或其继承类的所有实例中,只有一个$insert实例。

您之所以在两个var_dump中都看到autoinsert_nRecord,是因为那是您创建的最后一个对象。

考虑一下这个小变化:

$a = new gtRecord();
var_dump(gtRecord::$insert); // autoinsert_gtRecord
$b = new nRecord();    
var_dump(nRecord::$insert);  // autoinsert_nRecord
var_dump(gtRecord::$insert); // autoinsert_nRecord (because it was the last one set)

在第一个var_dump之后,值为_gtRecord,但一旦创建了nRecord对象,静态属性(对于所有dbPreparedObject对象)就会更改为nRecord,因为这是最后一个类。

因此,如果您计划拥有该类的多个实例,$insert就不能是静态的,因为它不会总是包含给定代码所需的值,因为静态$insert属性只有一个副本对所有对象都是相同的。一旦在一个对象中更改了它,就可以在所有对象中更改它。

因此,我们需要问为什么$insert需要是静态的,或者你还有什么其他选择,这样你就不会遇到这个问题。