0

我一直在研究 PHP 5.3.x 中的一小部分遵循 Active Record 模式的类。但是,在使用静态属性时,我遇到了一个问题。这是我一直在测试的代码:

<?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"

但是,我希望第一个字符串读取autoinsert_gtRecord.

似乎没有由子类实例化的静态属性是捆绑在一起的。有没有办法将它们分开而不public static $insert = ""在每个子类中声明?

4

1 回答 1

1

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

您看到autoinsert_nRecord这两个var_dumps 的原因是因为那是您创建的最后一个对象。

考虑这个微小的变化:

$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需要是静态的或者你有什么其他的选择,这样你就不会遇到这个问题。

于 2012-07-09T15:52:38.733 回答