The function of the static variable inside cannot contain a singleton reference

I noticed strange behavior with singlots in PHP, there is no better way to explain this, but with an example.

Let's say I have the following singleton class:

class Singleton { protected function __construct() { // Deny direct instantion! } protected function __clone() { // Deny cloning! } public static function &Instance() { static $Instance; echo 'Class Echo'.PHP_EOL; var_dump($Instance); if (!isset($Instance)) { $Instance = new self; } return $Instance; } } 

And the following function:

 function Test($Init = FALSE) { static $Instance; if ($Init === TRUE && !isset($Instance)) { $Instance =& Singleton::Instance(); } echo 'Function Echo'.PHP_EOL; var_dump($Instance); return $Instance; } 

And when I use the following:

 Test(TRUE); Test(); Singleton::Instance(); 

Output:

 Class Echo NULL Function Echo object(Singleton)#1 (0) { } Function Echo NULL Class Echo object(Singleton)#1 (0) { } 

As you can see, the stored link inside the function is lost after execution, even if the variable is static. Also note that the static variable inside the class method works fine.

Is this normal, or am I doing something wrong?

+4
source share
2 answers

This behavior is documented :

Zend Engine 1, which controls PHP 4, implements static and global for variables in terms of references . For example, a true global variable imported inside a function area with a global operator actually creates a reference to the global variable. This can lead to unexpected behavior.

This behavior has not changed since ZE1, and the decision is simply not to assign a reference to a static variable, therefore:

 $Instance = Singleton::Instance(); 

Update

I simplified the problem below:

 function test2($init = false, $value = null) { static $test; if ($init) { $test =& $value; } var_dump($test); } $v = 1; test2(true, $v); test2(); 

Output:

 int(1) NULL 
+6
source

This is a normal template for singleton in php. Note: the $ instance is a static property, not a static variable inside a function.

I'm having trouble figuring out the reasons, but your code above can be fixed by doing one of the following:

1) Delete the task assignment in the test function ( $Instance =& Singleton::Instance(); becomes $Instance = Singleton::Instance(); )

2) Delete the return by reference in the instance method ( public static function &Instance() will become public static function Instance() )

3) Or both 1 and 2.

 class Singleton{ protected static $instance; protected function __construct(){ } protected function __clone(){ throw new Exception("Cannot clone a Singleton"); } public static function getInstance(){ if(!isset(static::$instance)){ static::$instance = new static(); } return static::$instance; } } 
+2
source

Source: https://habr.com/ru/post/1494416/


All Articles