Я смотрел на источник для Drupal 7, и я нашел некоторые вещи, которых я раньше не видел. Я сделал некоторые первоначальные взгляды в руководстве php, но это не объясняло эти примеры.
Что ставит ключевое слово static
в переменной внутри функции?
function module_load_all($bootstrap = FALSE) { static $has_run = FALSE
Он заставляет функцию запоминать значение данной переменной ( $has_run
в вашем примере) между несколькими вызовами.
Вы можете использовать это для разных целей, например:
function doStuff() { static $cache = null; if ($cache === null) { $cache = '%heavy database stuff or something%'; } // code using $cache }
В этом примере if
будет выполняться только один раз. Даже если doStuff
несколько вызовов doStuff
.
Похоже, что никто не упоминал до сих пор, что статические переменные в разных экземплярах одного и того же класса остаются их состоянием. Поэтому будьте осторожны при написании кода OOP.
Учти это:
class Foo { public function call() { static $test = 0; $test++; echo $test . PHP_EOL; } } $a = new Foo(); $a->call(); // 1 $a->call(); // 2 $a->call(); // 3 $b = new Foo(); $b->call(); // 4 $b->call(); // 5
Если вы хотите, чтобы статическая переменная запоминала свое состояние только для текущего экземпляра класса, вам лучше придерживаться свойства класса, например:
class Bar { private $test = 0; public function call() { $this->test++; echo $this->test . PHP_EOL; } } $a = new Bar(); $a->call(); // 1 $a->call(); // 2 $a->call(); // 3 $b = new Bar(); $b->call(); // 1 $b->call(); // 2
В следующем примере:
function a($s){ static $v = 10; echo $v; $v = $s; }
Первый вызов
a(20);
будет выводить 10
, затем $v
равно 20
. Переменная $v
не является сборкой мусора после завершения функции, так как это статическая (нединамическая) переменная. Переменная останется в пределах своей сферы действия до тех пор, пока сценарий не закончится полностью.
Поэтому следующий вызов
a(15);
затем выдает 20
, а затем устанавливает значение $v
равным 15
.
Статический работает так же, как и в классе. Переменная является общей для всех экземпляров функции. В вашем конкретном примере, как только функция запускается, $ has_run имеет значение TRUE. Все будущие прогоны функции будут иметь $ has_run = TRUE. Это особенно полезно в рекурсивных функциях (в качестве альтернативы передаче счетчика).
Статическая переменная существует только в области локальной функции, но она не теряет своего значения, когда выполнение программы выходит из этой области.
статическая переменная в функции означает, что независимо от того, сколько раз вы вызываете функцию, существует только одна переменная.
<?php class Foo{ protected static $test = 'Foo'; function yourstatic(){ static $test = 0; $test++; echo $test . "\n"; } function bar(){ $test = 0; $test++; echo $test . "\n"; } } $f = new Foo(); $f->yourstatic(); // 1 $f->yourstatic(); // 2 $f->yourstatic(); // 3 $f->bar(); // 1 $f->bar(); // 1 $f->bar(); // 1 ?>
Чтобы расширить ответ Ян
Если вы расширяете класс со статическими переменными, отдельные расширенные классы будут содержать свой «собственный» статический указатель, который используется совместно между экземплярами.
<?php class base { function calc() { static $foo = 0; $foo++; return $foo; } } class one extends base { function e() { echo "one:".$this->calc().PHP_EOL; } } class two extends base { function p() { echo "two:".$this->calc().PHP_EOL; } } $x = new one(); $y = new two(); $x_repeat = new one(); $x->e(); $y->p(); $x->e(); $x_repeat->e(); $x->e(); $x_repeat->e(); $y->p();
выходы:
один: 1
два : 1
один: 2
один : 3 <- x_repeat
один: 4
one : 5 <- x_repeat
два : 2
Внутри функции static
означает, что переменная будет сохранять свое значение каждый раз, когда функция вызывается в течение срока службы загрузки страницы.
Поэтому в примере, который вы $has_run
, если вы дважды вызываете функцию, если она задает значение $has_run
true
, тогда функция сможет узнать, что она ранее была вызвана, потому что $has_run
все равно будет равен true
когда функция начинается второй раз.
Использование ключевого слова static
в этом контексте описано в руководстве по PHP здесь: http://php.net/manual/en/language.variables.scope.php