Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP returning static variable by reference

Ignore the namespaces etc could any one explain why I can't return a reference to my static array? Effectively the class is a getter and setter. I wanted to use static methods as the class will never need to be instantiated again throughout the applications life cycle.

I understand what I'm doing might just be "bad practice" - any more knowledge on this matter would be appreciated.

namespace xtend\core\classes; 
use xtend\core\classes\exceptions;

class registry {

private static $global_registry = array();

private function __construct() {}

public static function add($key, $store) {
    if (!isset(self::$global_registry[$key])) {
        self::$global_registry[$key] = $store;
    } else {
        throw new exceptions\invalidParameterException(
            "Failed to add the registry. The key $key already exists."
        );
    }
}

public static function remove($key) {
    if (isset(self::$global_registry[$key])) {
        unset(self::$global_registry[$key]);
    } else {
        throw new exceptions\invalidParameterException(
            "Cannot remove key $key does not exist in the registry"
        );
    }
}

public static function &get($key) {
    if (isset(self::$global_registry[$key])) {
        $ref =& self::$global_registry[$key];
        return $ref;
    } else {
        throw new exceptions\invalidParameterException(
            "Cannot get key $key does not exist in the registry"
        );
    }
}

}

Using it like this

$test = array("my","array");
\xtend\core\classes\registry::add("config",&$test);
$test2 =& \xtend\core\classes\registry::get("config");
$test2[0] = "notmy";    
print_r($test);

Your would presume I would get back

array("notmy","array");

But I just get back the original.

like image 286
Jonathan Tizard Avatar asked Nov 25 '22 14:11

Jonathan Tizard


1 Answers

Executive summary:

class Registry {
    private static $global_registry = array();

    public static function Add($key, &$value){
        static::$global_registry[$key] =& $value;
    }
    public static function &Get($key){
        return static::$global_registry[$key];
    }
    public static function Remove($key){
        unset(static::$global_registry[$key]);
    }
}

$test = array("my", "array");
Registry::Add("config", $test);
$test2 =& Registry::Get("config");
$test2[0] = "notmy";    
var_dump($test);

It's really quite simple once you understand how it works:

  • Firstly, the add function must pass by reference, otherwise the value that is seen in the function isn't even the value that you have passed in.

  • Secondly, when storing the value in $global_registry, we must assign by reference. Otherwise, the value stored isn't even the value seen in the function.

  • Thirdly, we must return by reference by putting an ampersand in the function declaration. You have already done this, except this code:

$ref =& self::$global_registry[$key]; // redundant line
return $ref;

Is the same as this code:

return self::$global_registry[$key];

Because in the line public static function &get, we have already declared that the return value is a reference.

  • And Lastly, we need to assign the returned reference by reference, which you have also did:
$test2 =& Registry::Get("config");

As you can can see, the whole chain must be by reference. If any one of the step is not done by referece, it wouldn't work.

like image 114
Pacerier Avatar answered Nov 27 '22 03:11

Pacerier