【问题标题】:Implement/extend/inherit/... the same __get and __set function for all my classes为我的所有类实现/扩展/继承/...相同的 __get 和 __set 函数
【发布时间】:2011-06-22 22:38:20
【问题描述】:

我不喜欢“getProperty”和“setProperty”之类的函数,所以我研究了 __get 和 __set 函数。

我创建了一个运行良好的结构。现在我想在我的大部分课程中使用它。我如何做到这一点(记住我可能想用另一个类扩展一个类)而不必复制代码?

我已经知道接口不是一个选项,因为这就是复制代码(如果我理解正确的话)

以下是函数,以防万一:

/**
 * Simply return the property
 */
private function __get($strProperty) {

    if(array_key_exists($strProperty, $this->properties)){

        $c = $this->properties[$strProperty];

        // Fetch the wanted data and store it in memory
        if(!$c['fetched']){

            if($c['type'] == 'array'){
                $proptr = $this->md->fetch_array('SELECT ' . $c['field'] . ' FROM ' . $c['table'] . ' WHERE ' . $c['where'], $c['table'].$c['field'].$c['where'], 1000);
                $c['value'] = $proptr;
            }else {
                $proptr = $this->md->query_first('SELECT ' . $c['field'] . ' FROM ' . $c['table'] . ' WHERE ' . $c['where'], $c['table'].$c['field'].$c['where'], 1000);
                $c['value'] = $proptr[$c['field']];
            }


        }

        return $c['value'];

    } else {
        return $this->$strProperty;
    }

}

/**
 * Set the property, and update the database when needed
 */
private function __set($strProperty, $varValue) {

    // If the property is defined in the $properties array, do something special
    if (array_key_exists($strProperty, $this->properties)) {

        // Get the fieldname
        $field = $this->properties[$strProperty]['field'];

        $data[$field] = $varValue;

        $this->md->update(TABLE_USER, $data, $this->properties[$strProperty]['where']);

        // And store the value here, too
        $this->$strProperty = $varValue;

    } else {
        $this->$strProperty = $varValue;
    }
}

【问题讨论】:

  • ehm ...只是创建一个类并从它继承?那太容易了,因此恐怕我不明白您的真正问题:X
  • 这真的有效吗?私有魔法函数?
  • @KingCrunch:真正的问题可能是,您只能从 PHP 中的一个类扩展。
  • 哦,我从别人那里得到了这个想法,那里的魔法方法是私有的。无论哪种方式都可以,但是如果您可以放心,我会更改它;)无论如何:如果我将其放在一个类中并继承该类,则我无法继承其他任何东西。
  • @KingCrunch:我试过了;)你得到一个警告,并且该方法被强制公开。

标签: php


【解决方案1】:

如果我理解正确,您希望在一组对象中自动处理属性数组,如果是这样,那么这应该相应地工作:

abstract class Prototype
{
    protected $properties = array();

    public function __get($key)
    {
        if(property_exists($this,'properties') && is_array($this->properties))
        {
            return isset($this->properties[$key]) ? $this->properties[$key] : null;
        }
    }

    public function __set($key,$value)
    {
        if(property_exists($this,'properties') && is_array($this->properties))
        {
            $this->properties[$key] = $value;
        }
    }
}

这只是一个基本概念,但我刚刚测试过并且工作正常,你可以像这样简单地扩展你的根类:

class User extends Prototype{}

然后像通常使用 get 和 set 魔术方法设置值一样使用,将方法设置为 protected 将允许方法的可见性在所有子类中可用,但不允许在对象之外。

这是你要找的吗?

【讨论】:

  • 根类?哦,所以我创建了某种“继承链”?那么 B 类扩展 A 类扩展 Prototype?
  • 是的,这就是为什么我们将其称为继承,B 扩展 A,C 扩展 B,这是从 A 和 B 继承所有内容:)
  • 我尝试了您的代码示例,但出现错误:The magic method __set() must have public visibility and cannot be static
  • 我在发布和测试后将它们设置为受保护,所以是的,它们必须是公开的,没有办法解决这个问题:(
【解决方案2】:

你想要的是traits,但它们在 PHP 5.3 中不可用。

现在你需要扩展如下类:

class Foo_Bar extends Foo { }
class Foo extends GetterSetter {}

基类是你的 getter/setter 类。

【讨论】:

  • traits 看起来很性感,不知道他们是在 5.4 中的 :)
【解决方案3】:

我使用一个核心类,并从中扩展我的所有其他类;

class xs_Core {
   // generic handling code here
}

class xs_Request extends xs_Core {
   // inherits the generic stuff above
}

还有我自己的特定于应用程序的扩展;

class my_own_special_request extends xs_Request {
   // my stuff
}

必须从创建继承树结构的角度进行思考。

说了这么多,还有一点要说的是像这样的魔术getter和setter继承了整个堆栈,它与在你的代码和一般代码中查找错误有关维护。几个更大的框架正在回避这种做法,并且已经开始进行大规模的重写以摆脱无声失败的诅咒,Joomla 现在只是一个更大的例子。正是出于这个原因,我刚刚重新编写了自己的框架 (xSiteable)。它正在成为一种反模式,所以要小心行事。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-02
    • 2011-09-16
    • 2012-12-17
    • 2014-04-29
    • 2016-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多