【问题标题】:PHP how to use magic method with static class? [duplicate]PHP如何在静态类中使用魔术方法? [复制]
【发布时间】:2013-03-03 20:24:16
【问题描述】:

我正在尝试将数组转换为对象。我想使用魔术方法 - 带有静态属性的 __get 和 __set。

我的代码:

class UserData {
    private static  $id, $name, $login;

    public function __get($var)
    {
        return self::$var;
    }
    public function __set($var, $val)
    {
        self::{$var} = $val;
    }
}

以及设置:

foreach($userArray as $key => $val) 
    {
        DaneBilingowe::${$key} = $val;
    }

错误: 致命错误:无法访问私有属性 UserData::$id

是否可以使用具有静态属性的魔术方法?

【问题讨论】:

  • PHP Manual: Property overloading only works in object context. (...) will not be triggered in static context. 差不多总结了。
  • @Alvin 如果你有它的对象上下文,你可以访问静态上下文。这是废话,但可能。看我的回答。
  • "DaneBilingowe::${$key} = $val;" - 你真的为每个用户创建了一个子类吗?这就是实例的用途。 $daneBillingowe = new UserData('Dane Billingowe'); - 问题解决了吗?

标签: php class static


【解决方案1】:

简而言之,没有。

__get()__set() 是实例方法。它们本质上是构成stdClass() 的函数,它是一个实例。

如果你必须以这种方式设置静态内容,你可以给类一个 stdClass 参数和一个单例结构,让你可以神奇地设置和获取数据。

例如:

class UserData {
    protected static $_instance;
    protected $_data = array();

    public static function get_instance() {
        static $initialized = FALSE;

        if ( ! $initialized) {
            self::$_instance = new UserData;
            $initialized = TRUE;
        }

        return self::$_instance;
    }

    public function __get($var) {
        $self = self::get_instance();

        return isset($self->_data[$var]) ? $self->_data[$var] : NULL;
    }

    public function __set($var, $val) {
        $self = self::get_instance();

        $self->_data[$var] = $val;
    }
}

那么你可以去:

 $UserData =& UserData::get_instance();
 $UserData->var = 'val';

 echo $UserData->var; // prints 'val'

但是,我不建议在 PHP 中使用 Singleton,因为它们毫无意义。您可以在帖子Best practice on PHP singleton classes 中阅读一些原因。

使用静态类或实例类。

Magic getter 和 setter 是快捷方式。您可以使用普通的 setter 和 getter 实现相同的行为。下面的示例提供了相同的功能,但意图更加明确:

class UserData {
    protected $id, $name, $login;

    public static function set_name($name) {
        self::$name = $name;
    }

    public static function set_login($login) {
        self::$login = $login;
    }

    public static function get_id() {
        return self::$id;
    }

    public static function get_name() {
        return self::$name;
    }

    public static function get_login() {
        return self::login;
    }
}

请注意在上面的代码中 $id 是如何不可写的。它只是可读的。 $name 和 $login 是可读写的。使用普通的 setter 和 getter 来控制读写更容易,错误更少。魔术方法就是这样,魔术,而且魔术通常不是具体的,在代码中也不太容易理解。

我想说的最后一点是,为什么 UserData 会是静态的?除非您的整个代码中只有 1 个用户,否则将其设为静态是没有意义的。也许我没有得到全貌,但是应该实例化具有 id 和 name 的东西,以便您可以拥有多个实例。否则,为什么要有id,因为类本身是唯一的。

【讨论】:

    【解决方案2】:

    如果你真的想在静态属性上使用魔法方法,你可以,但你需要一个实例。虽然看起来不合理,但作为程序员本身就完全不合理:)

    另外,用户定义的类和对象在 php 中不是动态的。 你不能那么容易地向它们添加变量......所以你可以使用下面的模式:

    class UserData {
        private static  $id, $name, $login, $arr = [];
    
        public function __get($var){
            return (array_key_exists(self::$arr, $var)? self::$arr[$var]:null;
        }
    
        public function __set($var, $val){
            self::$arr[$var] = $val;
        }
    }
    

    然后设置:DaneBilingowe 是什么?我现在不在这里...但是:

    $inst = new UserData();
    
    foreach($userArray as $key => $val){
        $inst->$key = $val;
    }
    

    会起作用的。

    但请注意,它仅适用于类(静态)内存。 此外,由于没有对设置名称进行适当的过滤,因此可能会发生奇怪的事情。 (这意味着你应该添加它们)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-21
      • 2014-11-29
      • 1970-01-01
      • 1970-01-01
      • 2015-09-13
      • 1970-01-01
      • 1970-01-01
      • 2015-01-04
      相关资源
      最近更新 更多