Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assigning a static variable to another static variable. Why does it throw an error?

Class Test {
   private static $one = ['a','b'];
   private static $two = Test::$one; // Throws an error
   // Error : syntax error, unexpected '$one', expecting 'identifier' or 'class'
}

Why does it throw an error and what is the way here to make $two = $one?

like image 904
Suhail Gupta Avatar asked Oct 19 '22 07:10

Suhail Gupta


1 Answers

It is a limitation of the PHP compiler and it is explained in the documentation:

Like any other PHP static variable, static properties may only be initialized using a literal or constant before PHP 5.6; expressions are not allowed. In PHP 5.6 and later, the same rules apply as const expressions: some limited expressions are possible, provided they can be evaluated at compile time.

The key statement here is: "provided they can be evaluated at compile time".

From the error message you receive I can tell you are using PHP 5. On PHP 7 the error message was reworded to clearly state the problem. It says "Constant expression contains invalid operations".

The declaration of the first static variable ($one) compiles because you initialize it with a constant expression. ['a','b'] is an array of strings, it can be evaluated at the compile time, everything is fine.

The second static variable ($two) is initialized with a non-constant expression (Test::$one). Test::$one is a variable. You can tell that its value initial value is known at the compile time (see the paragraph above) and the expression can be evaluated at the compile time.

This kind of behaviour requires a deeper analysis of the code at the compile time. It is probably implemented in C++ or Java compilers but these are languages that are compiled only once and the code they generate is stored in a file and executed or interpreted later. The PHP compiler doesn't work this way for a reason. It compiles the script before each execution, that's why it aims to complete the compilation as fast as possible and doesn't put much effort in code analysis and optimizations.

Update:

As @deceze specifies in a comment, the expression Test::$one cannot be evaluated in the declaration of $two because it uses class Test that is not completely defined at this point. Even the compilers of other languages that allow this kind of reference cannot compute the value of Test::$one when they reach the declaration of $two. They need to use a second compilation pass to be able to evaluate it.

like image 145
axiac Avatar answered Oct 21 '22 05:10

axiac