Pull to refresh

Comments 28

UFO just landed and posted this here
Да, конечно на php.net это написано.
Просто не так подробно, и не так понятно (как мне кажется). Эта статья написана чтобы подробно и доступным языком постараться объяснить документацию (даже в тегах поставил документация), чтобы прочитав можно было освежить в памяти забытое, или разобраться в теме если в ней плаваешь.
UFO just landed and posted this here
Ух, помню времена, когда был только новичком в программировании, и первый мой язык был — php. Если со статическими переменными в функциях всё было более-менее понятно, то в классах постоянно путался со статическими переменными/методами. Прочитал не одну статью, но полное понимание пришло всё же на практике, когда начал писать свой класс для работы с внешним апи. Либо я туповат, либо это действительно с первого (и со второго) взгляда выглядит не так-то просто и однозначно
то в классах постоянно путался со статическими переменными/методами

*со статическими свойствами
«Могут быть присвоены только константы и константные выражения» -> Может быть инициализирована только…
Да, точно, немного корявое выражение получилось, но смысл думаю будет понятно там далее по тексту идет пояснение.

Видимо вот этот абзац из документации меня сбил
Начиная с PHP 5.6 стало возможным присвоить этим переменным значения, являющиеся результатом выражения, но нельзя использовать для этого функцию, так это вызовет ошибку разбора.


UFO just landed and posted this here

Я ставлю.
Лично мне понравилась доступность изложения и то, как автор раскрывает специфичные моменты.
Вообще я не вижу ничего криминального в разнообразии ленты — можно выбрать что почитать. А вот лично вы, с вашими намеками про недостаток «мотивации/концентрации» на прочтение сложных статей, фактически уже хамите всему сообществу хабра. Лично мне хватает и концентрации и мотивации и прочего на прочтение больших и сложных статей. Когда интересно и полезно.

UFO just landed and posted this here
В чем-то была замечана аномалия их поведения?
Честно, так и не понял, что хотел автор донести. Если глянуть на самый первый комментарий, то человек прав.
Ваши 4 характеристики знакомы всем, кто хотя бы раз использовал эти статические свойства в классах.
А если не использовали, то дорога на php.net, а не сюда
В чем-то была замечана аномалия их поведения?

Я не говорию что это неправильное поведение, или ошибочное, именно странное
Вот хотя бы этот пример для меня странный, две функции практически одинаковые (разница в них при беглом, да даже и при внимательном осмотре, не должна повлиять на их поведение), с одинкаовыми параметрами передаными, но возвращают разные результаты.
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
UFO just landed and posted this here
Это же не реальный код. Конечно нет смысла дважды ее объявлять в двух строках подряд.
Смысл в том что функции одинаковые по сути, но ведут себя по разному, это мне показалось странным. В документации написано что может быть присвоена однажды, но оказывается есть такой нюанс, про него ничего не написано. Стоит ли про это писать в документации — конечно нет, потому что такое использование неприемлимо. Исчезла ли от этого странность в работе — тоже нет.
UFO just landed and posted this here

Это две странные функции, и обе они ведут себя странно. Зачем стрелять себе в ногу, тем более дважды?

Вообще, ни чего странно тут нет, все логично (за исключением того, что программист решил несколько раз объявить static $var).
При компиляции конструкция static обрабатывается по порядку и последующая инициализация переписывает предыдущую. При выполнении static уже не обрабатывается (можно считать что в райнтайме этих строк уже нет совсем), поэтому, при первом вызове staticVarWrong $var = 5, а в staticVarRight $var = 0;

Именно, нюанс в том, что инициализируется переменная при объявлении функции (условный компайлтайм), при первом require/include или прямом запуске файла, а не при первом вызове функции. Нет никакого счётчика вызовов.

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

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


function fake(){
    static $r='qwerty';
    $t = 'asdfgh';
}

line     #* E I O op                 fetch          ext  return  operands
---------------------------------------------------------------------------
   3     0  E >   BIND_STATIC                                    !0, 'r'
   4     1        ASSIGN                                         !1, 'asdfgh'
   5     2      > RETURN                                         null

Строка 3 — привязываем статическую переменную $r к области видимости функции.
Строка 4 — присваиваем обычной переменной $t значение.


Обратите внимание, что присвоение значения переменной $r в коде отсутствует.

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

$one = function ($i) {
	static $var = 0;
	$var += $i;

	var_dump($var);
};

$one(1); //1
$one(5); //6

$two = clone($one);

$one(5); //11

$two(5); //11
$two(5); //16

Никаких "уже запущенная (как минимум один раз) функция". Перенесите clone на две строки вверх и $two(5) выведет 5. После вашей первой строки $var уже проинициализировна нулём, хотя ни разу ещё не вызывалась, и при клонировании это значение тоже склонируется.

Sign up to leave a comment.

Articles