web-dev-qa-db-ja.com

PHP静的変数

$count = 5;
function get_count()
{
    static $count = 0;
    return $count++;
}
echo $count;
++$count;
echo get_count();
echo get_count();

私はそれが5 0 1を出力すると推測しました、それは正しいですが、私はより良い説明が必要ですか?

41
omg

関数内の変数$countは、グローバル$count変数とは一切関係ありません。 staticキーワード はCまたはJavaと同じです。つまり、この変数を1回だけ初期化し、関数の終了時にその状態を保持します。つまり、実行が関数に再び入ると、内部の$ countがすでに初期化され、1として最後に保存されていることがわかり、その値が使用されます。

71
soulmerge
$count = 5; // "outer" count = 5

function get_count()
{
    static $count = 0; // "inner" count = 0 only the first run
    return $count++; // "inner" count + 1
}

echo $count; // "outer" count is still 5 
++$count; // "outer" count is now 6 (but you never echoed it)

echo get_count(); // "inner" count is now + 1 = 1 (0 before the echo)
echo get_count(); // "inner" count is now + 1 = 2 (1 before the echo)
echo get_count(); // "inner" count is now + 1 = 3 (2 before the echo)

これがあなたの心をクリアすることを願っています。

41
Alix Axel

両方とも$ countと呼ばれる2つの別個の変数がありますが、それらは異なる scope を持っています。最初の変数は明示的に宣言されていませんが、最初に割り当てたときに存在します。

2番目の変数(メソッド内)は、そのメソッドにのみ表示されます。 静的 であるため、その値は同じメソッドの複数の実行間で保持されます。割り当て$count = 0;は、メソッドが最初に実行されたときにのみ実行されます。

インクリメント演算子(++)の場合、評価の結果は、値がbeforeであるため、( 単項 )変数名の後に演算子が続きます。はい、出力は5、0、1になります。
return ++$count;と書くと、結果は5、1、2になります。

注:既存のコードにある++$countは、評価の結果が破棄されるため、実質的に$count++と同等です。 $count変数に対する効果は同じです。1ずつ増加します。

13
Thorarin

最初のエコー:最初の行で宣言する変数$ countを提供します。

2番目のエコー:get_countを呼び出して、静的変数$ countを作成し(したがって、この関数のコンテキスト内にあります)、静的変数をインスタンス化するときにゼロに設定します。 return $ count ++は、通常コードで避ける行の1つですが、本質的には、値が返された後にインクリメントされます。

3番目のエコー:同様に、get_countの前回の呼び出し後に0が1にインクリメントされました。ここでも同じことが起こります。1を返し、値を2にインクリメントします。

それは助けになりますか、それとも実際にはもっと混乱しますか?

5
Fenton

まず、関数内の$ countと関数外の$ countは2つの異なる変数です。これが、最初の出力が5を出力する理由の説明です。

ここで、静的の場合:静的とは、関数が初めて実行されるときに、ローカル変数が一度だけ作成されることを意味します。その後のすべての関数実行では同じ変数が使用されるため、最後の関数実行での変数の最新の値がまだそこにあります。

したがって、最初にget_count()を呼び出すと、変数は0に設定されてから返されます。復帰後、変数はインクリメントされます。

関数を2回目に呼び出しても、変数は1です。この値が返され、2にインクリメントされます。

0

PHPには、オブジェクト指向のPHPで静的メソッドとプロパティを定義するために広く使用されているよく知られているstaticキーワードがありますが、static関数内で使用して、静的変数を定義することもできます。

「静的変数」とは?

静的変数は、プログラムの実行がこのスコープを離れたときに値を失わない場合、関数のスコープで定義された通常の変数とは異なります。静的変数を使用する次の例を考えてみましょう。

function countSheep($num) {
 static $counter = 0;
 $counter += $num;
 echo "$counter sheep jumped over fence";
}

countSheep(1);
countSheep(2);
countSheep(3);

結果:

1 sheep jumped over fence
3 sheep jumped over fence
6 sheep jumped over fence

staticなしで$counterを定義した場合、エコーされるたびに、関数に渡される$numパラメーターと同じ値になります。 staticを使用すると、追加の回避策なしでこの単純なカウンターを作成できます。

静的変数のユースケース

  1. 関数への結果的な呼び出しの間に値を保存するため。
  2. Paramsとして渡す方法がない(または目的がない)場合に、再帰呼び出しの間に値を保存する。
  3. 通常は1回取得する方が適切な値をキャッシュします。たとえば、サーバー上の不変ファイルの読み取り結果。

トリック

静的変数はローカル関数スコープにのみ存在します。定義されている関数の外部からアクセスすることはできません。そのため、その関数の次の呼び出しまで値が変更されないことを確認できます。

静的変数は、スカラーまたはスカラー式としてのみ定義できます(PHP 5.6以降)。少なくともこの記事が書かれた時点では、他の値を割り当てると必然的に失敗につながります。あなたはあなたのコードの次の行でそうすることができます:

function countSheep($num) {
  static $counter = 0;
  $counter += sqrt($num);//imagine we need to take root of our sheep each time
  echo "$counter sheep jumped over fence";
}

結果:

2 sheep jumped over fence
5 sheep jumped over fence
9 sheep jumped over fence

静的関数は、同じクラスのオブジェクトのメソッド間で一種の「共有」です。次の例を参照すると理解しやすくなります。

class SomeClass {
  public function foo() {
    static $x = 0;
    echo ++$x;
  }
}

$object1 = new SomeClass;
$object2 = new SomeClass;

$object1->foo(); // 1
$object2->foo(); // 2 oops, $object2 uses the same static $x as $object1
$object1->foo(); // 3 now $object1 increments $x
$object2->foo(); // 4 and now his twin brother

これは、同じクラスのオブジェクトでのみ機能します。オブジェクトが異なるクラスに属している場合(相互に拡張している場合でも)、静的変数の動作は期待どおりです。

関数の呼び出し間で値を保持する唯一の方法は静的変数ですか?

関数呼び出し間で値を保持する別の方法は、クロージャーを使用することです。 PHP 5.3で導入されました。つまり、関数スコープ内の変数セットへのアクセスを、それらにアクセスする唯一の方法となる別の匿名関数に制限できます。クロージャー変数は、構造化プログラミングで「クラス定数」(値によってクロージャーに渡された場合)または「プライベートプロパティ」(参照により渡された場合)のような概念を(多かれ少なかれうまく)OOP概念。

後者では、実際には静的変数の代わりにクロージャーを使用できます。使用するものは常に開発者が決定しますが、静的変数は再帰で作業する場合に間違いなく有用であり、開発者が気付くに値することに注意する必要があります。

0
alex_edev