Magic __get getter for static properties in PHP

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.

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


No, it is not possible.

Quoting the manual page of __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, __callStatic has been added ; but there is no __getStatic nor __setStatic yet ; even if the idea of having/coding them often comes back on the php internals@ mailling-list.

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


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");
  }
}

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 if statement to limit the variables that are accessible, or else it would defeat the purpose of having them be private or protected.

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.

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.");
    }
}