php PHP中静态属性的魔术__get getter

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1279382/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 01:51:38  来源:igfitidea点击:

Magic __get getter for static properties in PHP

phpooppropertiesgetter

提问by treznik

public static function __get($value)

does not work, and even if it did, it so happens that I already need the magic __get getter for instance properties in the same class.

不起作用,即使它起作用了,碰巧我已经需要魔术 __get getter 用于同一类中的实例属性。

This probably is a yes or no question, so, it is possible?

这可能是一个是或否的问题,所以,有可能吗?

回答by Pascal MARTIN

No, it is not possible.

不,这是不可能的。

Quoting the manual page of __get:

引用__get手册页

Member overloading only works in object context. These magic methods will not be triggered in static context. Therefore these methods can not be declared static.

成员重载仅适用于对象上下文。这些魔术方法不会在静态上下文中触发。因此这些方法不能被声明为静态的。


In PHP 5.3, __callStatichas been added ; but there is no __getStaticnor __setStaticyet ; even if the idea of having/coding them often comes back on the php internals@ mailling-list.


在 PHP 5.3 中,__callStatic已添加;但没有__getStatic也不__setStatic之中; 即使拥有/编码它们的想法经常出现在 php internals@mailling-list 上。

There is even a Request for Comments: Static classes for PHP
But, still, not implemented (yet ? )

甚至还有一个评论请求:PHP 的静态类
但是,仍然没有实现(还没有实现?)

回答by mbrzuchalski

Maybe someone still need this:

也许有人还需要这个:

static public function __callStatic($method, $args) {

  if (preg_match('/^([gs]et)([A-Z])(.*)$/', $method, $match)) {
    $reflector = new \ReflectionClass(__CLASS__);
    $property = strtolower($match[2]). $match[3];
    if ($reflector->hasProperty($property)) {
      $property = $reflector->getProperty($property);
      switch($match[1]) {
        case 'get': return $property->getValue();
        case 'set': return $property->setValue($args[0]);
      }     
    } else throw new InvalidArgumentException("Property {$property} doesn't exist");
  }
}

回答by kmuenkel

Very nice mbrzuchalski. But it seems to only work on public variables. Just change your switch to this to allow it to access private/protected ones:

非常好的姆布祖哈尔斯基。但它似乎只适用于公共变量。只需将您的开关更改为此即可允许它访问私有/受保护的:

switch($match[1]) {
   case 'get': return self::${$property->name};
   case 'set': return self::${$property->name} = $args[0];
}

And you'd probably want to change the ifstatement to limit the variables that are accessible, or else it would defeat the purpose of having them be private or protected.

并且您可能希望更改if语句以限制可访问的变量,否则会破坏将它们设为私有或受保护的目的。

if ($reflector->hasProperty($property) && in_array($property, array("allowedBVariable1", "allowedVariable2"))) {...)

So for example, I have a class designed to pull various data for me out of a remote server using an ssh pear module, and I want it to make certain assumptions about the target directory based on what server it's being asked to look at. A tweaked version of mbrzuchalski's method is perfect for that.

例如,我有一个类旨在使用 ssh pear 模块从远程服务器中为我提取各种数据,我希望它根据要求查看的服务器对目标目录做出某些假设。mbrzuchalski 方法的调整版本非常适合这种情况。

static public function __callStatic($method, $args) {
    if (preg_match('/^([gs]et)([A-Z])(.*)$/', $method, $match)) {
        $reflector = new \ReflectionClass(__CLASS__);
        $property = strtolower($match[2]). $match[3];
        if ($reflector->hasProperty($property)) {
            if ($property == "server") {
                $property = $reflector->getProperty($property);
                switch($match[1]) {
                    case 'set':
                        self::${$property->name} = $args[0];
                        if ($args[0] == "server1") self::$targetDir = "/mnt/source/";
                        elseif($args[0] == "server2") self::$targetDir = "/source/";
                        else self::$targetDir = "/";
                    case 'get': return self::${$property->name};
                }
            } else throw new InvalidArgumentException("Property {$property} is not publicly accessible.");
        } else throw new InvalidArgumentException("Property {$property} doesn't exist.");
    }
}

回答by Jokerius

Also, you can get static properties accessing them like member properties, using __get():

此外,您可以使用 __get() 获取访问它们的静态属性,就像成员属性一样:

class ClassName {    
    private static $data = 'smth';

    function __get($field){
        if (isset($this->$field)){
            return $this->$field;
        }
        if(isset(self::$$field)){  
            return self::$$field;  // here you can get value of static property
        }
        return NULL;
    }
}

$obj = new ClassName();
echo $obj->data; // "smth"

回答by Gilberto

try this:

尝试这个:

class nameClass{
    private static $_sData = [];
    private static $object = null;
    private $_oData = [];

    public function __construct($data=[]){
        $this->_oData = $data;
    }

    public static function setData($data=[]){
        self::$_sData = $data;
    }

    public static function Data(){
        if( empty( self::$object ) ){
            self::$object = new self( self::$_sData ); 
        }
        return self::$object;
    }

    public function __get($key) {
        if( isset($this->_oData[$key] ){
            return $this->_oData[$key];
        }
    }

    public function __set($key, $value) {
        $this->_oData[$key] = $value;
    }
}

nameClass::setData([
    'data1'=>'val1',
    'data2'=>'val2',
    'data3'=>'val3',
    'datan'=>'valn'
]);

nameClass::Data()->data1 = 'newValue';
echo(nameClass::Data()->data1);
echo(nameClass::Data()->data2);

回答by Jonny

Combining __callStaticand call_user_funcor call_user_func_arraycan give access to static properties in PHP class

组合__callStaticcall_user_funccall_user_func_array可以访问 PHP 类中的静态属性

Example:

例子:

class myClass {

    private static $instance;

    public function __construct() {

        if (!self::$instance) {
            self::$instance = $this;
        }

        return self::$instance;
    }

    public static function __callStatic($method, $args) {

        if (!self::$instance) {
            new self();
        }

        if (substr($method, 0, 1) == '$') {
            $method = substr($method, 1);
        }

        if ($method == 'instance') {
            return self::$instance;
        } elseif ($method == 'not_exist') {
            echo "Not implemented\n";
        }
    }

    public function myFunc() {
        echo "myFunc()\n";
    }

}

// Getting $instance
$instance = call_user_func('myClass::$instance');
$instance->myFunc();

// Access to undeclared
call_user_func('myClass::$not_exist');