Php статическая переменная в функции
Готовимся к собеседованию по PHP: ключевое слово «static»
Не секрет, что на собеседованиях любят задавать каверзные вопросы. Не всегда адекватные, не всегда имеющие отношение к реальности, но факт остается фактом — задают. Конечно, вопрос вопросу рознь, и иногда вопрос, на первый взгляд кажущийся вам дурацким, на самом деле направлен на проверку того, насколько хорошо вы знаете язык, на котором пишете.
Попробуем разобрать «по косточкам» один из таких вопросов — что значит слово «static» в PHP и зачем оно применяется?
Ключевое слово static имеет в PHP три различных значения. Разберем их в хронологическом порядке, как они появлялись в языке.
Значение первое — статическая локальная переменная
Однако всё меняется, если мы перед присваиванием поставим ключевое слово static:
Подводные камни статических переменных
Разумеется, как всегда в PHP, не обходится без «подводных камней».
Камень первый — статической переменной присваивать можно только константы или константные выражения. Вот такой код:
с неизбежностью приведет к ошибке парсера. К счастью, начиная с версии 5.6 стало допустимым присвоение не только констант, но и константных выражений (например — «1+2» или «[1, 2, 3]»), то есть таких выражений, которые не зависят от другого кода и могут быть вычислены на этапе компиляции
Камень второй — методы существуют в единственном экземпляре.
Тут всё чуть сложнее. Для понимания сути приведу код:
Такое поведение может быть неожиданным для неподготовленного к нему разработчика и послужить источником ошибок. Нужно заметить, что наследование класса (и метода) приводит к тому, что всё-таки создается новый метод:
Вывод: динамические методы в PHP существуют в контексте классов, а не объектов. И только лишь в рантайме происходит подстановка «$this = текущий_объект»
Значение второе — статические свойства и методы классов
В объектной модели PHP существует возможность задавать свойства и методы не только для объектов — экземпляров класса, но и для класса в целом. Для этого тоже служит ключевое слово static:
Для доступа к таким свойствам и методам используются конструкции с двойным двоеточием («Paamayim Nekudotayim»), такие как ИМЯ_КЛАССА::$имяПеременной и ИМЯ_КЛАССА:: имяМетода().
Само собой разумеется, что у статических свойств и статических методов есть свои особенности и свои «подводные камни», которые нужно знать.
Особенность вторая — static не аксиома!
Обратное не совсем верно:
И кстати, всё написанное выше относится только к методам. Использование статического свойства через «->» невозможно и ведет к фатальной ошибке.
Значение третье, кажущееся самым сложным — позднее статическое связывание
Разработчики языка PHP не остановились на двух значениях ключевого слова «static» и в версии 5.3 добавили еще одну «фичу» языка, которая реализована тем же самым словом! Она называется «позднее статическое связывание» или LSB (Late Static Binding).
Понять суть LSB проще всего на несложных примерах:
Ключевое слово self в PHP всегда значит «имя класса, где это слово написано». В данном случае self заменяется на класс Model, а self::$table — на Model::$table.
Такая языковая возможность называется «ранним статическим связыванием». Почему ранним? Потому что связывание self и конкретного имени класса происходит не в рантайме, а на более ранних этапах — парсинга и компиляции кода. Ну а «статическое» — потому что речь идет о статических свойствах и методах.
Немного изменим наш код:
Теперь вы понимаете, почему PHP ведёт себя в этой ситуации неинтуитивно. self был связан с классом Model тогда, когда о классе User еще ничего не было известно, поэтому и указывает на Model.
Для решения этой дилеммы был придуман механизм связывания «позднего», на этапе рантайма. Работает он очень просто — достаточно вместо слова «self» написать «static» и связь будет установлена с тем классом, который вызывает данный код, а не с тем, где он написан:
Это и есть загадочное «позднее статическое связывание».
Нужно отметить, что для большего удобства в PHP кроме слова «static» есть еще специальная функция get_called_class(), которая сообщит вам — в контексте какого класса в данный момент работает ваш код.
Ключевое слово static в PHP
Nov 24, 2019 · 4 min read
Сигнатура метода
Эту логику можно извлечь в отдельный класс, который известен как шаблон проектирования статическая фабрика (Static Factory):
Свойства
В отличие от обычных свойств, изменение значения статического свойства во время выполнения программы повлияет на все экземпляры содержащего свойство класса. Даже на те, для которых еще не созданы экземпляры. Таким образом, статические свойства можно рассматривать в качестве “констант изменяемого класса”. На статические свойства можно ссылаться только с помощью оператора разрешения области видимости.
Благодаря природе статических свойств их можно использовать для реализации шаблона одиночка (Singleton). Одиночка содержит один и тот же экземпляр класса на протяжении всего выполнения программы.
Переменные
В контексте статической функции переменные сохраняют свое значение даже после выхода программы из области видимости содержащей их функции. В контексте метода класса статические переменные обладают дополнительным поведением, подобным статическим свойствам: изменения их значений отражаются во всех экземплярах класса. Несмотря на схожесть со статическими свойствами, статические переменные доступны только в теле функции или метода.
Статические переменные часто используются в технике оптимизации под названием мемоизация. Ее целью является ускорение дорогостоящей операции за счет кэширования результатов и сохранения их для последующего вызова с теми же параметрами.
Анонимные функции
Статические анонимные функции не обладают такой широтой вариантов использования, как обычные анонимные функции. Стоит отметить, что статические анонимные функции немного улучшают производительность и могут использоваться в любых экземплярах при отсутствии необходимости привязки содержащего класса к анонимной функции.
Позднее статическое связывание
Позднее статическое связывание демонстрирует другой вариант использования ключевого слова static : в контексте наследования. В этом контексте static относится к вызываемому классу, а не к тому, для которого был определен метод: на него, в свою очередь, будет ссылаться self или __CLASS__ :
Заключение
Мы рассмотрели несколько примеров использования ключевого слова static в PHP. Хотя сценарии использования умозрительны, они очень реалистичны. Польза, которую они могут принести вашему коду, может быть огромной. По крайней мере, знакомство с этими способами использования static сделает вас сильным разработчиком.
Php статическая переменная в функции
= 1 ; /* глобальная область видимости */
Ключевое слово global
Сначала пример использования global :
Пример #1 Использование global
Пример #3 Суперглобальные переменные и область видимости
Использование ключевого слова global вне функции не является ошибкой. Оно может быть использовано в файле, который включается внутри функции.
Использование статических ( static ) переменных
Другой важной особенностью области видимости переменной является статическая переменная. Статическая переменная существует только в локальной области видимости функции, но не теряет своего значения, когда выполнение программы выходит из этой области видимости. Рассмотрим следующий пример:
Пример #4 Демонстрация необходимости статических переменных
Пример #5 Пример использования статических переменных
Пример #6 Статические переменные и рекурсивные функции
Статическим переменным можно присвоить значения, являющиеся результатом выражения, но нельзя использовать для этого функцию, так это вызовет ошибку разбора.
Пример #7 Объявление статических переменных
Статические объявления вычисляются во время компиляции скрипта.
Ссылки с глобальными ( global ) и статическими ( static ) переменными
Результат выполнения данного примера:
$obj1 = get_instance_ref ();
$still_obj1 = get_instance_ref ();
echo «\n» ;
$obj2 = get_instance_noref ();
$still_obj2 = get_instance_noref ();
?>
Результат выполнения данного примера:
Этот пример демонстрирует, что при присвоении ссылки статической переменной она не запоминается, когда вы вызываете функцию &get_instance_ref() во второй раз.
User Contributed Notes 42 notes
Some interesting behavior (tested with PHP5), using the static-scope-keyword inside of class-methods.
$a = new sample_class ();
$b = new sample_class ();
Maybe it’s senseless to post that.. cause if you want to have the behaviour that I expected, you can simply use a variable of the object itself:
Please note for using global variable in child functions:
This won’t work correctly.
function foo () <
$f_a = ‘a’ ;
Static variables do not hold through inheritance. Let class A have a function Z with a static variable. Let class B extend class A in which function Z is not overwritten. Two static variables will be created, one for class A and one for class B.
Look at this example:
As you can see, class A and B are using different static variables even though the same function was being used.
Took me longer than I expected to figure this out, and thought others might find it useful.
I created a function (safeinclude), which I use to include files; it does processing before the file is actually included (determine full path, check it exists, etc).
Problem: Because the include was occurring inside the function, all of the variables inside the included file were inheriting the variable scope of the function; since the included files may or may not require global variables that are declared else where, it creates a problem.
My solution: Thus, to make all my global variables available to the files included with my safeinclude function, I had to add the following code to my safeinclude function (before variables are used or file is included)
Pretty simple approach that I could not find anywhere online; only other approach I could find was using PHP’s eval().
Take to heart this hard-won rule:
Declare AT THE TOP any variable that is to be global.
Both at the top of the FILE
AND at the top of any FUNCTION where it appears.
Why AT THE TOP? So it is sure to be declared before use. Otherwise a non-global version of the variable will be created and your code will fail.
Why at the top of a FUNCTION? Because otherwise the function will refer only to its local version of the variable and your code will fail.
Why at the top of the FILE? Because someday—a day that you cannot now imagine—you will want to «include» the file. And when you do, instances of the variable outside functions will not go in the global scope and your code will fail. (When the «include» is inside a calling function, variables in the included file go into the scope of the calling function.)
Странные они, статические переменные в PHP
Дисклеймер: данная статья не явит вам какого то откровения и не откроет третий глаз, но позволит разобраться в не очень очевидном вопросе более детально. Мне по крайней мере при ее написании она в этом помогла. Если вы матерый волк в php то можете не читать, опытным человекам думаю не повредит пробежать глазами, освежить так сказать в памяти, остальным будет норм.
Статические переменные, в php это особый вид переменных, которые объявляются при помощи ключевого слова static.
От обычных переменных они отличаются тем что (далее в статье эти пункты будут рассмотрены более подробно):
1. Могут быть присвоены только константы и константные выражения
Это значит что в статическую переменную не может быть присвоен результат работы какой-либо функции или метода, или вообще что-либо что еще не известно на этапе компиляции. То есть вот такое объявление не сработает
а вот так вполне возможно
2. Время жизни статической переменной не ограничено временем жизни области видимости в которой она объявлена
Постараюсь объяснить что тут я имел в виду. Возможно допущу какие-то неточности в терминологии, но суть постараюсь передать как можно точнее. Сравним с обычной переменной. Если внутри функции объявить переменную, то она по умолчанию является локальной переменной, то есть она объявлена в локальной области видимости (области видимости этой функции). В этом случае контекстом данной функции будет локальная область видимости. После того как функция отработала и вернула результат, ее область видимости или ее контекст, со всеми переменными внутри нее будет уничтожена.
Если же мы внутри функции объявляем статическую переменную, то она также объявляется в локальной области видимости, но ее контекстом будет не локальная область видимости, а сама функция.
(Далее самый трудный момент для объяснения, передаю только суть, без подробностей, как объявляются функции в php сколько им выделяется памяти и что в этой памяти лежит). Получается так, при вызове функции, для нее интерпретатором создается локальная область видимости именно в ней объявляются все локальные переменные и ф-ции, и к ней как к своему контексту они и привязаны. Объявляя же переменную в локальной области видимости с помощью static, этой переменной в качестве контекста назначается сама функция, и эта переменная будет существовать до тех пор пока существует сама функция. Это нечто похожее на js, когда функция является объектом, в который можно присваивать произвольные свойства и методы. Тут так же только функция в php является объектом не для php, а для более низкого ЯП.
А вот пример который наглядно покажет что статическая переменная принадлежит функции (или хранится в функции, или ее контекстом является функция уж извините не знаю как это правильно назвать).
Немного поменяем пример, а именно не присвоим, а клонируем
Что можно с этим сделать — это классический пример счетчика вызова функции.
Но в связи с распространением ООП в таком виде статические переменные встречаются редко, так как в основном приходится оперировать классами и методами (о реализации static в них напишу отдельную статью)
3. могут быть определены в скрипте лишь однажды
Это значит что если статическая переменная уже объявлена, и ей присвоено значение, то последующие присвоения не перезапишут уже присвоенное значение, а вернут существующее.
Тут переменная $var в первом вызове функции staticVar в первой ее строке была присвоена, потом перезаписана во второй строке. Но уже в дальнейших вызовах ни в первой ни во второй строке она не была переприсвоена, а вернула то что уже было в предыдущем вызове
Еще страннее при первом вызове staticVar в первой строке она была присвоена, потом во второй строке переприсвоена, затем с ней было произведено действие сложения, и уже после этого при попытки ее переприсвоить даже в рамках первого вызова функции она вернула уже лежащее в ней значение. Меня это довольно сильно позабавило.
4. не уничтожаются до конца выполнения скрипта
Не вижу особого смысла объяснять этот пункт, тем более что из примеров все видно. Пока работает скрипт и пока существует функция для которой объявлена статическая переменная, эта переменная существует.
Как планируется — это первая статья по static, впереди еще ООП, статические поля, методы.
Ну конечно если это хоть кому-то будет интересно и жестко не заминусуется.
Php статическая переменная в функции
Эта страница описывает использование ключевого слова static для определения статических методов и свойств. static также может использоваться для определения статических переменных и позднего статического связывания. Для получения информации о таком применении ключевого слова static обратитесь по вышеуказанным страницам.
Объявление свойств и методов класса статическими позволяет обращаться к ним без создания экземпляра класса. К ним также можно получить доступ статически в созданном экземпляре объекта класса.
Статические методы
Пример #1 Пример статического метода
Foo :: aStaticMethod ();
$classname = ‘Foo’ ;
$classname :: aStaticMethod ();
?>
Статические свойства
Пример #2 Пример статического свойства
Результат выполнения данного примера в PHP 8 аналогичен:
User Contributed Notes 28 notes
Here statically accessed property prefer property of the class for which it is called. Where as self keyword enforces use of current class only. Refer the below example:
public function static_test ()<
This is also possible:
You misunderstand the meaning of inheritance : there is no duplication of members when you inherit from a base class. Members are shared through inheritance, and can be accessed by derived classes according to visibility (public, protected, private).
The difference between static and non static members is only that a non static member is tied to an instance of a class although a static member is tied to the class, and not to a particular instance.
That is, a static member is shared by all instances of a class although a non static member exists for each instance of class.
class Derived extends Base
<
public function __construct()
<
$this->a = 0;
parent::$b = 0;
>
public function f()
<
$this->a++;
parent::$b++;
>
>
$i1 = new Derived;
$i2 = new Derived;
To check if a method declared in a class is static or not, you can us following code. PHP5 has a Reflection Class, which is very helpful.
It is important to understand the behavior of static properties in the context of class inheritance:
— Static properties defined in both parent and child classes will hold DISTINCT values for each class. Proper use of self:: vs. static:: are crucial inside of child methods to reference the intended static property.
— Static properties defined ONLY in the parent class will share a COMMON value.
declare( strict_types = 1 );
$a = new staticparent ;
$a = new staticchild ;
It should be noted that in ‘Example #2’, you can also call a variably defined static method as follows:
Static variables are shared between sub classes
class Child1 extends MyParent <
class Child2 extends MyParent <
To check if a function was called statically or not, you’ll need to do:
(I’ll add this to the manual soon).
The static keyword can still be used (in a non-oop way) inside a function. So if you need a value stored with your class, but it is very function specific, you can use this:
echo aclass::b(); //24
echo aclass::b(); //36
echo aclass::b(); //48
echo aclass::$d; //fatal error
Starting with php 5.3 you can get use of new features of static keyword. Here’s an example of abstract singleton class:
abstract class Singleton <
/**
* Prevent direct object creation
*/
final private function __construct ()
/**
* Prevent object cloning
*/
final private function __clone ()
On PHP 5.2.x or previous you might run into problems initializing static variables in subclasses due to the lack of late static binding:
If the init() method looks the same for (almost) all subclasses there should be no need to implement init() in every subclass and by that producing redundant code.
Solution 1:
Turn everything into non-static. BUT: This would produce redundant data on every object of the class.
Short example on a DataRecord class without error checking:
Regarding the initialization of complex static variables in a class, you can emulate a static constructor by creating a static function named something like init() and calling it immediately after the class definition.
/*
this is the example to use new class with static method..
i hope it help
*/
It’s come to my attention that you cannot use a static member in an HEREDOC string. The following code
function __construct()
<
echo
Inheritance with the static elements is a nightmare in php. Consider the following code:
class DerivedClassOne extends BaseClass <
>
class DerivedClassTwo extends BaseClass <
>
At this point I think it is a big pity inheritance does not work in case of static variables/methods. Keep this in mind and save your time when debugging.
Hi, here’s my simple Singleton example, i think it can be useful for someone. You can use this pattern to connect to the database for example.
$objA = MySingleton :: getInstance (); // Object created!
$objB = MySingleton :: getInstance ();