PHP的静态属性的Magic __get getter

tre*_*nik 60 php oop getter properties

public static function __get($value)
Run Code Online (Sandbox Code Playgroud)

不起作用,即使它确实如此,我也需要在同一个类中使用magic __get getter作为实例属性.

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

Pas*_*TIN 63

不,这是不可能的.

引用__get手册页:

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


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

甚至还有一个Request for Comments:用于PHP的静态类
但是,仍然没有实现(还没有?)

  • @webarto同意了,但考虑到我们在PHP领域,他们是一流的OOP功能哈哈 (3认同)
  • @DejanMarjanovic他们有自己的用例. (3认同)

小智 17

也许有人仍然需要这个:

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");
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是做什么的? (8认同)

Cla*_*ore 5

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

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

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

if ($reflector->hasProperty($property) && in_array($property, array("allowedBVariable1", "allowedVariable2"))) {...)
Run Code Online (Sandbox Code Playgroud)

例如,我有一个类旨在使用 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.");
    }
}
Run Code Online (Sandbox Code Playgroud)