Magic __get getter for static properties in PHP

PhpOopPropertiesGetter

Php Problem Overview


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?

Php Solutions


Solution 1 - Php

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 ? )

Solution 2 - Php

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

Solution 3 - Php

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

Solution 4 - Php

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

Solution 5 - Php

Combining __callStatic and call_user_func or call_user_func_array can give access to static properties in PHP class

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');

Solution 6 - Php

Also, you can get static properties accessing them like member properties, using __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"

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiontreznikView Question on Stackoverflow
Solution 1 - PhpPascal MARTINView Answer on Stackoverflow
Solution 2 - PhpmbrzuchalskiView Answer on Stackoverflow
Solution 3 - PhpkmuenkelView Answer on Stackoverflow
Solution 4 - PhpGilbertoView Answer on Stackoverflow
Solution 5 - PhpJonny View Answer on Stackoverflow
Solution 6 - PhpJokeriusView Answer on Stackoverflow