関数内でstaticな変数

PHPの日本語マニュアルだと「静的変数」と呼ばれるもの、になります( http://php.net/manual/ja/language.variables.scope.php#language.variables.scope.static )。
端的には、マニュアルに書いてある通り「プログラム実行がこのスコープの外で行われるようになっ てもその値を失わないません」というものになります。

………で終わるとこのnoteがわりと「用無し」になってしまうので(笑)、少しかみ砕いていきましょう。

まず、すべからくプログラミング言語の変数には「スコープ(有効範囲)」というものがあります。
んで、PHPには「global」と「local」の2つのスコープが存在します( http://php.net/manual/ja/language.variables.scope.php )。

classや関数(メソッド含む)の中にない、一番外側で宣言した変数は「globalスコープ」の変数になります。

<?php
$i = 10;
$s = 'hoge';

このような場合の、$iや$sが「globalスコープの変数」です。
一方で、関数(メソッド含む)の中で使っている変数が「localスコープの変数」になります。

<?php
function hoge()
{
   $i = 10;
   $s = 'hoge';
}

こういった場合の、上述の$iや$sは「localスコープの変数」になります。

PHPでは
・関数の外側では「globalスコープの変数しか触れない」
・関数の内側では「自分の関数の中で使っているlocalスコープの変数しか触れない」
というルールがあります。

そのため、例えば

<?php
$i = 10; // ここはglobalスコープ
//
function hoge()
{
   echo $i; // ここはlocalスコープ
}
//
hoge();

と書いても、hoge()関数の中では「globalスコープの$i」は(原則として)触れないので、echoの結果は

Notice: Undefined variable: i in ...

となります。
この辺が「関数の内側では「自分の関数の中で使っているlocalスコープの変数しか触れない」」というルールの故、になります。

さて。
globalスコープの変数は、基本的に「プログラムが終わるまで生きています」が、localスコープの寿命は「そのスコープが終わるまで」です。
つまり

<?php
//
function hoge()
{
   $i = 10; // ここで$iが生まれる
   // XXXX 処理各種
} // 関数をぬけたら、hoge関数内の$iは消える

という寿命になります。
基本的にはこれで十分に事足りるのですが、時々「値を保持し続けて欲しい」と思う瞬間、というのが、ニーズ的には存在します。
そんな時に、ここのタイトルである「関数内でstaticな変数」というのを使うと、値を保持し続けることが出来るようになります。

わかりやすいコードで確認をしてみましょう。

<?php
function hoge()
{
   // 変数の準備
   static $i = 0;
   $j = 0;
   // 変数のインクリメント
   $i ++;
   $j ++;
   // 表示
   echo "i is {$i}, j is {$j}\n";
}
// hogeを何回かcall
hoge();
hoge();
hoge();

結果は、こうなります。

i is 1, j is 1
i is 2, j is 1
i is 3, j is 1

$jは、元々説明した通りですね。
localな変数は「そのスコープ(今回は hoge() 関数)が終わるまで」なので、毎回0が代入され、毎回+1されるので、常に1を出します。

これと異なる動きをしているのが、$iです。
少し砕いて説明をしていきましょう。

   static $i = 0;

と書かれた場合。
初めてここを通る時は「$iが存在していない」ので、処理としては「$iの領域を確保しつつ、初期代入である = 0に従って、0を代入する」ように動きます。
二回目以降ここを通る時は「$iが存在している」ので、処理としては「この行を読み飛ばします」。

結果として
・初回は、$iに0を入れてから++なので、1を出力
・二回目は、$iに1が入っていてからの++なので、2を出力
・三回目は、$iに2が入っていてからの++なので、3を出力
という風に動きます。

この「関数内でstaticな変数」は、そんなにしょっちゅう使うモノではないのですが。
知っていると、要所要所で便利なので、是非、覚えておいてください。

この記事が気に入ったらサポートをしてみませんか?