PHP中如何覆盖父对象的静态属性并让父对象访问新值?

发布于 2024-09-10 12:48:01 字数 2750 浏览 4 评论 0原文

这就是我所拥有的:所有可以持久保存在数据库上的对象都扩展了 DatabaseObject 抽象类,该抽象类具有实际监视属性更改和运行数据库查询的所有逻辑代码。

我使用两个静态变量来定义特定于对象的详细信息。我一般在基类中定义它们,然后假设我在实际的数据库对象中覆盖它们。

问题是:当父类中的代码实际执行时,它使用旧的父值而不是当前对象值。

这是基类的代码:

abstract class DatabaseObject {

    public $id;

    private static $databaseTable = NULL;
    private static $databaseFields = array();

    private $data = array();
    private $changedFields = array();

    public function IDatabaseObject($id) {
    $this->id = $id;
    $this->data = Database::GetSingle(self::$databaseTable, $id);

    Utils::copyToObject($this, $this->data, self::$databaseFields);
    }

    public static function Load($id) {
    return new self($userID);
    }

    public static function Create($data) {

    $id = Database::Insert(self::$databaseTable, $data);

    return new self($id);
    }

    public function Save() {
    $data = Utils::copyFromObject($this, $this->changedFields);

    Database::Update(self::$databaseTable, $data, $this->id);

    }

    public function __constructor() {
    // We do this to allow __get and __set to be called on public vars
    foreach(self::$databaseFields as $field) {
        unset($this->$field);
    }
    }

    public function __get($variableName) {
    return $this->$variableName;
    }

    public function __set($variableName, $variableValue) {
    // We only want to update what has been changed
    if(!in_array($variableName, $this->changedFields) && in_array($variableName, self::$databaseFields)) {
        array_push($this->changedFields, $variableName);
    }

    $this->$variableName = $variableValue;
    }
}

这是上面扩展基类的对象之一的代码:

class Client extends DatabaseObject {

    public static $databaseTable = "clients";
    public static $databaseFields = array("name","contactName","primaryUserID","email","is_active","rg","cpf","cnpj","ie","addrType","addrName","addrNumber","addrComplement","addrPostalCode","addrNeighborhood","addrCity","addrState","addrCountry","phoneLandline","phoneFax","phoneMobile");

    public $name;
    public $contactName;

    public $primaryUserID;
    public $email;

    public $is_active;

    public $rg;
    public $cpf;
    public $cnpj;
    public $ie;

    public $addrType;
    public $addrName;
    public $addrNumber;
    public $addrComplement;
    public $addrPostalCode;
    public $addrNeighborhood;
    public $addrCity;
    public $addrState;
    public $addrCountry;

    public $phoneLandline;
    public $phoneFax;
    public $phoneMobile;

    public static function Load($id) {
 return new Client($id);
    }

}

我在这里做错了什么?还有其他方法可以达到相同的结果吗?

一个简短的附录:我在类主体中声明属性主要是为了让 NetBeans 的自动完成功能看到它。

This is what I have: All objects that can be persisted on the database extend the DatabaseObject abstract class, which has all the logic code to actually watch for attribute changes and run the databas queries.

I'm using two static variables to define object-specific details. I define them generically in the base class, and then supposedly I overwrite them in the actual database objects.

The problem is: When the code in the parent class is actually executed, it uses the old parent value instead of the current object value.

Here's the code for the base class:

abstract class DatabaseObject {

    public $id;

    private static $databaseTable = NULL;
    private static $databaseFields = array();

    private $data = array();
    private $changedFields = array();

    public function IDatabaseObject($id) {
    $this->id = $id;
    $this->data = Database::GetSingle(self::$databaseTable, $id);

    Utils::copyToObject($this, $this->data, self::$databaseFields);
    }

    public static function Load($id) {
    return new self($userID);
    }

    public static function Create($data) {

    $id = Database::Insert(self::$databaseTable, $data);

    return new self($id);
    }

    public function Save() {
    $data = Utils::copyFromObject($this, $this->changedFields);

    Database::Update(self::$databaseTable, $data, $this->id);

    }

    public function __constructor() {
    // We do this to allow __get and __set to be called on public vars
    foreach(self::$databaseFields as $field) {
        unset($this->$field);
    }
    }

    public function __get($variableName) {
    return $this->$variableName;
    }

    public function __set($variableName, $variableValue) {
    // We only want to update what has been changed
    if(!in_array($variableName, $this->changedFields) && in_array($variableName, self::$databaseFields)) {
        array_push($this->changedFields, $variableName);
    }

    $this->$variableName = $variableValue;
    }
}

And here's the code for one of the objects extending the base class above:

class Client extends DatabaseObject {

    public static $databaseTable = "clients";
    public static $databaseFields = array("name","contactName","primaryUserID","email","is_active","rg","cpf","cnpj","ie","addrType","addrName","addrNumber","addrComplement","addrPostalCode","addrNeighborhood","addrCity","addrState","addrCountry","phoneLandline","phoneFax","phoneMobile");

    public $name;
    public $contactName;

    public $primaryUserID;
    public $email;

    public $is_active;

    public $rg;
    public $cpf;
    public $cnpj;
    public $ie;

    public $addrType;
    public $addrName;
    public $addrNumber;
    public $addrComplement;
    public $addrPostalCode;
    public $addrNeighborhood;
    public $addrCity;
    public $addrState;
    public $addrCountry;

    public $phoneLandline;
    public $phoneFax;
    public $phoneMobile;

    public static function Load($id) {
 return new Client($id);
    }

}

What am I doing wrong here? Is there another way I can achieve the same result?

A brief addendum: I declare the attributes in the class body mainly to let it be seen by the NetBeans' auto-complete feature.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我的鱼塘能养鲲 2024-09-17 12:48:01

您正在寻找后期静态绑定

所以你需要使用:

static::$databaseTable

而不是

self::$databaseTable

这个功能从 PHP 5.3 开始可用。在 PHP 5.2 中模拟这一点非常困难,原因有两个: get_called_class 仅从 PHP 5.3 起才可用。因此,它也必须使用 debug_backtrace 进行模拟。第二个问题是,如果您有被调用的类,您仍然可能无法使用 $usedClass::$property 因为这也是 PHP 5.3 的功能。这里需要使用eval或者Reflection。所以我真的希望你有 PHP 5.3 ;)

You are looking for Late Static Binding.

So you need to use:

static::$databaseTable

instead of

self::$databaseTable

This feature is available as of PHP 5.3. Simulating this in PHP 5.2 is very hard, because of two reasons: get_called_class is available only since PHP 5.3, too. Therefore it must be simulated, too, using debug_backtrace. The second problem is, that if you have the called class, you still may not use $calledClass::$property because this is a PHP 5.3 feature, too. Here you need to use eval or Reflection. So I do hope that you have PHP 5.3 ;)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文