They are strange static variables in PHP

Disclaimer: this article will not reveal any kind of revelation to you and will not open the third eye, but will allow you to understand the not-so-obvious question in more detail. At least when I wrote it, she helped me in this. If you are a seasoned wolf in php then you can not read it, I think it will not hurt experienced people to run through their eyes, refresh them in memory, so to speak, the rest will be normal.







So...







Static variables in php is a special kind of variable that is declared using the static keyword .







static $foo = 3;
      
      





They differ from ordinary variables in that (later in the article these points will be considered in more detail):







  1. only constants and constant expressions can be assigned
  2. the lifetime of a static variable is not limited to the lifetime of the scope in which it was declared
  3. can be defined in the script only once
  4. not destroyed until the end of the script


Now in order.







1. Only constants and constant expressions can be assigned



This means that the result of the operation of any function or method cannot be assigned to a static variable, or in general anything that is not yet known at the compilation stage. That is, such an ad will not work







 static $var = foo();
      
      





but it’s quite possible







 static $var = 'some str'; static $varInt = 3 + 5;
      
      





2. The lifetime of a static variable is not limited to the lifetime of the scope in which it is declared



I’ll try to explain what I meant here. Perhaps I will make some inaccuracies in the terminology, but I will try to convey the essence as accurately as possible. Compare to a regular variable. If a variable is declared inside a function, then by default it is a local variable, that is, it is declared in the local scope (scope of this function). In this case, the context of this function will be the local scope. After the function has worked and returned the result, its scope or its context, with all the variables inside it, will be destroyed.







If we declare a static variable inside the function, then it is also declared in the local scope, but its context is not the local scope, but the function itself.







(Further, the most difficult moment to explain, I pass only the essence, without details, how functions are declared in php how much memory is allocated to them and what lies in this memory). It turns out this way, when a function is called, the interpreter creates a local scope for it, it is in it that all local variables and functions are declared, and they are attached to it as to their context. By declaring a variable in the local scope using static, the function itself is assigned to this variable as a context, and this variable will exist as long as the function itself exists. This is something like js when a function is an object into which you can assign arbitrary properties and methods. Here, too, only a function in php is an object not for php, but for a lower language.







 function echoStaticVar() { static $var = 0; $var++; var_dump($var); }; echoStaticVar(); //1 echoStaticVar(); //2 echoStaticVar(); //3
      
      





It can be seen that after the function terminates, the collector does not destroy the $ var variable as it would with a regular variable.







And here is an example that will clearly show that a static variable belongs to a function (or is stored in a function, or its function is the context, so I’m sorry I don’t know how to correctly name it).







 $one = function ($i) { static $var = 0; $var += $i; var_dump($var); }; $two = $one; $one(1); //1 $one(5); //6 $one(5); //11 $two(5); //16 $two(5); //21
      
      





Everything works as expected, because when assigning $ two = $ one; the function itself is not copied, but simply both of these variables will refer to the same memory area. Accordingly, the static variable $ var will be one for both $ one and $ two







We change the example a little, namely, we do not assign, but we clone







 // $two = $one; // $two = clone($one);
      
      





 $one = function ($i) { static $var = 0; $var += $i; var_dump($var); }; $two = clone($one); $one(1); //1 $one(5); //6 $one(5); //11 $two(5); //5 $two(5); //10
      
      





Now it turned out that $ one and $ two do not refer to the same function with one static variable $ var, but to two different functions that lie in different memory areas and each have its own static variable $ var. This is not a particularly obvious point, so you can stumble on it, if you certainly write code in a procedural style, which is probably already considered bad form, but this is not accurate).







What you can do about it is a classic example of a function call counter.

But in connection with the distribution of OOP in this form, static variables are rare, since basically you have to operate on classes and methods (I will write a separate article about the implementation of static in them)







3. can be defined in the script only once



This means that if a static variable is already declared, and a value is assigned to it, subsequent assignments will not overwrite the already assigned value, but will return the existing one.







 function staticVar($i) { static $var = 0; $var += $i; var_dump($var); }; staticVar(1); //1 staticVar(5); //6 staticVar(5); //11
      
      





It can be seen that if the static variable $ var each time had a value reassigned, then we would always get the result 1. But since it is not rewritten when reassigned, we get what we get.

True, there is one thing that can ruin everything. Within the framework of one function (more precisely, the first time the function is called), such a variable can be rewritten as many times as you like (in subsequent cases everything will work as stated). This behavior seemed to me strange and funny, especially if you play around with examples.







 function staticVar($i) { static $var = 0; static $var = 5; $var += $i; var_dump($var); }; staticVar(1); //6 staticVar(5); //11 staticVar(5); //16
      
      





Here the variable $ var in the first call to the staticVar function in its first line was assigned, then overwritten in the second line. But already in further calls, neither in the first nor in the second line she was reassigned, but returned what was already in the previous call







 function staticVar($i) { static $var = 0; // static $var = 5; //    $var += $i; static $var = 0; //    var_dump($var); }; staticVar(1); //1 staticVar(5); //6 staticVar(5); //11
      
      





Even stranger on the first call of staticVar in the first line, it was assigned, then in the second line it was reassigned (but unsuccessfully), then an addition action was performed with it, and already after that, when trying to reassign it even within the first function call, it returned the one already in her meaning.







 function staticVarWrong($i) { static $var = 0; static $var = 5; $var += $i; var_dump($var); }; //  staticVarWrong(1); //6 staticVarWrong(5); //11 staticVarWrong(5); //16 function staticVarRight($i) { static $var = 0; static $var = 5; $var += $i; static $var = 0; //    var_dump($var); }; //  staticVarRight(1); //1 staticVarRight(5); //6 staticVarRight(5); //11
      
      





That is, it turns out in almost the same methods, different behavior. Moreover, based on the description of how static variables should behave, the correct result is obtained in staticVarRight . In staticVarWrong it turns out (based on the behavior of the function) that in the second line of the function the variable has been redefined.

This amused me quite a lot.







4. are not destroyed until the end of the script



I don’t see much point in explaining this point, especially since everything is clear from the examples. While the script is running and while there is a function for which a static variable is declared, this variable exists.







As planned, this is the first article on static , ahead of it are OOP, static fields, methods.

Well, of course, if it is at least someone will be interested and not hard to blame.








All Articles