注: これは、PHP の変数スコープを扱う参考質問です。このパターンに当てはまる多くの質問を、この質問と重複するものとして閉じてください。
PHP の「変数スコープ」とは何ですか?ある .php ファイル内の変数に別の .php ファイルからアクセスできますか? 「未定義の変数」 エラーが時々表示されるのはなぜですか?
P粉3115638232023-10-20 10:03:09
関数スコープ内で定義された変数には外部からアクセスできませんが、関数の完了後にその値を使用できないわけではありません。 PHP には、オブジェクト指向 PHP で静的メソッドとプロパティを定義するために広く使用されているよく知られた static
キーワードがありますが、static
は関数内でも使用できることを覚えておく必要があります。静的変数を定義します。
静的変数は、関数スコープで定義された通常の変数とは異なり、プログラムの実行がスコープを離れても、静的変数の値は失われません。静的変数を使用した次の例を考えてみましょう:
リーリー ###結果:### リーリー static を使用せずに $counter
を定義すると、毎回エコーされる値は、関数に渡される $num
パラメーターと同じになります。この単純なカウンターは、追加の回避策なしで static
を使用して構築できます。
これは、同じクラスのオブジェクトにのみ適用されます。静的変数は、オブジェクトが異なるクラスに属している場合 (または相互に拡張している場合)、期待どおりに動作します。
静的変数は関数呼び出し間で値を保持する唯一の方法ですか?関数呼び出し間で値を保持するもう 1 つの方法は、クロージャを使用することです。クロージャは PHP 5.3 で導入されました。つまり、関数のスコープ内の特定の変数セットへのアクセスを、それらにアクセスする唯一の方法である別の匿名関数に制限することができます。クロージャ変数内にあると、構造化プログラミングの「クラス定数」(クロージャ内で値によって渡される場合) や「プライベート プロパティ」(参照によって渡される場合) などの OOP 概念を (多かれ少なかれうまく) エミュレートできます。
後者では、実際には静的変数の代わりにクロージャを使用できます。何を使用するかを決定するのは常に開発者次第ですが、静的変数は再帰を使用するときに間違いなく便利であり、開発者の注意を払う価値があることに注意してください。
P粉8951872662023-10-20 09:03:53
変数の「範囲」または「アクセスできる場所」は制限されています。 $foo = 'bar'; をアプリケーションの どこかに一度書いたからといって、
foo >他の場所## から $ を参照できるわけではありません。 # アプリケーション内で。変数
$foo には特定のスコープがあり、そのスコープ内で有効であり、同じスコープ内のコードのみが変数にアクセスできます。
PHP でスコープを定義するにはどうすればよいですか?
があります。これは、PHP に存在する唯一の範囲区切り文字です。関数内の変数は、その関数内でのみ使用できます。関数の外側の変数は関数の外側のどこでも使用できますが、関数の内部では使用できません。これは、PHP には特別なスコープ (global スコープ) があることを意味します。関数の外で宣言された変数はすべて、このグローバル スコープ内にあります。 ###例:### リーリー
$foo スコープ内にあり、$baz
は myFunc の local スコープ内にあります。 myFunc
内のコードのみが $baz にアクセスできます。 myFunc
の外部のコードのみが
$foo
にアクセスできます。どちらの当事者も他方にアクセスできません:
リーリー
スコープと含まれるファイル
ファイル境界分離されていません
範囲:
リーリー
b.phpリーリー
includeコードに適用されるルールは、他のコードに適用されるルールと同じです。 関数 のみに別個のスコープが適用されます。範囲を広げるために、コードをコピーして貼り付ける次のようなファイルを含めることを検討してください:
c.php
リーリー
上記の例では、
は myFunc 内に含まれており、
a.php 内の変数はローカル関数スコープのみを持ちます。 が
a.php 内のグローバル スコープ内にあるように見えるからといって、必ずしも実際にそうであるとは限りません。実際には、コードが含まれる/実行されるコンテキストによって異なります。
関数やクラス内の関数についてはどうすればよいでしょうか?
新しい function 宣言ごとに、新しいスコープが導入されます。これは非常に簡単です。
スコープの問題に対処するのは面倒に思えるかもしれませんが、
変数のスコープを制限することは、複雑なアプリケーションを作成する上で非常に重要です。
変数$bar
は、この範囲を関数パラメータとして明示的に入力します。この関数を見るだけで、使用する値がどこから来たのかは明らかです。次に、明示的に 値を返します。呼び出し元は、関数がどの変数を使用するか、その戻り値がどこから来るかを知っているという自信を持っています。
リーリー
変数のスコープを匿名関数に拡張する
を明示的に組み込みます。これは global
スコープとは異なることに注意してください。
間違った方法:
前述したように、グローバル スコープはやや特殊であり、関数はそこから変数を明示的にインポートできます。
リーリー
$foo
を使用および変更します。 ###こんなことしないで! (自分が何をしているのか本当に本当に理解している場合を除き、たとえそうであったとしても、それはやめてください!)
この関数の呼び出し元に表示される内容は次のとおりです:
リーリー
この関数に
が、副作用はあります。一部の関数は常に
を変更し、に何らかのグローバル状態を必要とするため、これは簡単に混乱を招く可能性があります。関数を ステートレスにして、何度呼び出しても、入力に対してのみ動作し、定義された出力を返すようにする必要があります。 可能であれば、いかなる方法でもグローバル スコープの使用を避けるべきです。最も確実なのは、変数をグローバル スコープからローカル スコープに「プル」しないことです。