Php static var in method

Странные они, статические переменные в PHP

Дисклеймер: данная статья не явит вам какого то откровения и не откроет третий глаз, но позволит разобраться в не очень очевидном вопросе более детально. Мне по крайней мере при ее написании она в этом помогла. Если вы матерый волк в php то можете не читать, опытным человекам думаю не повредит пробежать глазами, освежить так сказать в памяти, остальным будет норм.

Статические переменные, в php это особый вид переменных, которые объявляются при помощи ключевого слова static.

От обычных переменных они отличаются тем что (далее в статье эти пункты будут рассмотрены более подробно):

  1. могут быть присвоены только константы и константные выражения
  2. время жизни статической переменной не ограничено временем жизни области видимости в которой она была объявлена
  3. могут быть определены в скрипте лишь однажды
  4. не уничтожаются до конца выполнения скрипта

1. Могут быть присвоены только константы и константные выражения

Это значит что в статическую переменную не может быть присвоен результат работы какой-либо функции или метода, или вообще что-либо что еще не известно на этапе компиляции. То есть вот такое объявление не сработает

а вот так вполне возможно

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

2. Время жизни статической переменной не ограничено временем жизни области видимости в которой она объявлена

Постараюсь объяснить что тут я имел в виду. Возможно допущу какие-то неточности в терминологии, но суть постараюсь передать как можно точнее. Сравним с обычной переменной. Если внутри функции объявить переменную, то она по умолчанию является локальной переменной, то есть она объявлена в локальной области видимости (области видимости этой функции). В этом случае контекстом данной функции будет локальная область видимости. После того как функция отработала и вернула результат, ее область видимости или ее контекст, со всеми переменными внутри нее будет уничтожена.

Читайте также:  Красивый прайс лист css

Если же мы внутри функции объявляем статическую переменную, то она также объявляется в локальной области видимости, но ее контекстом будет не локальная область видимости, а сама функция.

(Далее самый трудный момент для объяснения, передаю только суть, без подробностей, как объявляются функции в php сколько им выделяется памяти и что в этой памяти лежит). Получается так, при вызове функции, для нее интерпретатором создается локальная область видимости именно в ней объявляются все локальные переменные и ф-ции, и к ней как к своему контексту они и привязаны. Объявляя же переменную в локальной области видимости с помощью static, этой переменной в качестве контекста назначается сама функция, и эта переменная будет существовать до тех пор пока существует сама функция. Это нечто похожее на js, когда функция является объектом, в который можно присваивать произвольные свойства и методы. Тут так же только функция в php является объектом не для php, а для более низкого ЯП.

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

Видно что после прекращения работы функции сборщик не уничтожает переменную $var как это было бы с обычной переменной.

А вот пример который наглядно покажет что статическая переменная принадлежит функции (или хранится в функции, или ее контекстом является функция уж извините не знаю как это правильно назвать).

$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

Все работает, как и ожидается, потому что при присвоении $two = $one; не копируется сама функция, а просто обе эти переменные будут ссылаться на одну и ту же область памяти. Соответственно и статическая переменная $var будет одна и для $one и для $two

Читайте также:  Basic html and css skills

Немного поменяем пример, а именно не присвоим, а клонируем

//вместо $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

Теперь получилось что $one и $two ссылаются не на одну и ту же функцию с одной статической переменной $var, а на две разные функции, лежащие в разный областях памяти, и имеющие каждая по своей статической переменной $var. Это не особо очевидный момент, по этому на нем можно споткнуться, если вы конечно вообще пишите код в процедурном стиле, что уже наверное считается дурным тоном, но это не точно).

Что можно с этим сделать — это классический пример счетчика вызова функции.
Но в связи с распространением ООП в таком виде статические переменные встречаются редко, так как в основном приходится оперировать классами и методами (о реализации static в них напишу отдельную статью)

3. могут быть определены в скрипте лишь однажды

Это значит что если статическая переменная уже объявлена, и ей присвоено значение, то последующие присвоения не перезапишут уже присвоенное значение, а вернут существующее.

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

Видно, что если бы в функции staticVar статической переменной $var каждый раз бы переприсваивалось значение то мы бы всегда получали в результате 1. Но так как при повторном присвоении она не перезаписывается, мы получаем то что мы получаем.
Правда тут есть одно но, которое может все испортить. В рамках одной функции (точнее при первом вызове функции), такую переменную можно перезаписать сколько угодно раз (при последующих все будет работать как и заявлено). Мне это поведение показалось странным и забавным, особенно если поиграться с примерами.

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

Тут переменная $var в первом вызове функции staticVar в первой ее строке была присвоена, потом перезаписана во второй строке. Но уже в дальнейших вызовах ни в первой ни во второй строке она не была переприсвоена, а вернула то что уже было в предыдущем вызове

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

Еще страннее при первом вызове staticVar в первой строке она была присвоена, потом во второй строке переприсвоена (но неуспешно), затем с ней было произведено действие сложения, и уже после этого при попытки ее переприсвоить даже в рамках первого вызова функции она вернула уже лежащее в ней значение.

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

То есть получается в практически одинаковый методах, разное поведение. Причем исходя из описания того как должны себя вести статические переменные то правильный результат получается именно в staticVarRight. В staticVarWrong получается (исходя из поведения функции) что во второй строке функции переменная была переопределена.
Меня это довольно сильно позабавило.

Читайте также:  Save txt utf 8 python

4. не уничтожаются до конца выполнения скрипта

Не вижу особого смысла объяснять этот пункт, тем более что из примеров все видно. Пока работает скрипт и пока существует функция для которой объявлена статическая переменная, эта переменная существует.

Как планируется — это первая статья по static, впереди еще ООП, статические поля, методы.
Ну конечно если это хоть кому-то будет интересно и жестко не заминусуется.

Источник

Оцените статью