注: これは、PHP で変数のスコープを処理するための参照用の質問です。このパターンに当てはまる多くの質問は、このパターンの重複としてクローズしてください。
PHPの「変数スコープ」とは何ですか? ある .php ファイルの変数は別のファイルでアクセスできますか? 「未定義変数」エラーが時々発生するのはなぜですか?
変数には、「スコープ」または「変数にアクセスできる場所」が制限されています。アプリケーションのどこか$foo = 'bar';
に一度書いたからといって、アプリケーション内の他の場所から参照できるわけではありません。変数には有効な特定のスコープがあり、同じスコープ内のコードのみが変数にアクセスできます。$foo
$foo
非常に単純です: PHP にはfunction scopeがあります。これは、PHP に存在する唯一のスコープ区切り文字です。関数内の変数は、その関数内でのみ使用できます。関数外の変数は、関数外のどこでも使用できますが、関数内では使用できません。これは、PHP に 1 つの特別なスコープ、つまりグローバルスコープがあることを意味します。関数の外で宣言された変数はすべて、このグローバル スコープ内にあります。
<?php
$foo = 'bar';
function myFunc() {
$baz = 42;
}
$foo
はグローバルスコープに$baz
あり、 内のローカルスコープにありmyFunc
ます。内部のコードのみmyFunc
が にアクセスできます$baz
。外部の コードのみmyFunc
が にアクセスできます$foo
。どちらも他方にアクセスできません:
<?php
$foo = 'bar';
function myFunc() {
$baz = 42;
echo $foo; // doesn't work
echo $baz; // works
}
echo $foo; // works
echo $baz; // doesn't work
ファイル境界はスコープを分離しません:
a.php
<?php
$foo = 'bar';
b.php
<?php
include 'a.php';
echo $foo; // works!
他のコードに適用されるのと同じルールがinclude
d コードに適用されfunction
ます。スコープの目的で、コードのコピーと貼り付けなどのファイルを含めることを考えることができます。
c.php
<?php
function myFunc() {
include 'a.php';
echo $foo; // works
}
myFunc();
echo $foo; // doesn't work!
上記の例では、a.php
内に含まれており、内myFunc
の変数はすべてa.php
ローカル関数スコープのみを持ちます。それらがグローバルスコープにあるように見えるa.php
からといって、必ずしもそうであるとは限りません。実際には、コードが含まれている/実行されているコンテキストに依存します。
すべての新しいfunction
宣言は新しいスコープを導入します。それはとても簡単です。
function foo() {
$foo = 'bar';
$bar = function () {
// no access to $foo
$baz = 'baz';
};
// no access to $baz
}
$foo = 'foo';
class Bar {
public function baz() {
// no access to $foo
$baz = 'baz';
}
}
// no access to $baz
スコープの問題に対処するのは面倒に思えるかもしれませんが、複雑なアプリケーションを作成するには、変数のスコープを制限することが不可欠です。宣言するすべての変数がアプリケーション内の他の場所から利用できる場合、変数全体をステップ実行することになり、何が何を変更したかを追跡する実際の方法はありません。変数に付けることができる適切な名前は非常に多く、変数 " $name
" を複数の場所で使用したい場合があります。この一意の変数名をアプリで 1 回しか使用できない場合は、変数が一意であること、および間違ったコードから間違った変数を変更していないことを確認するために、非常に複雑な命名スキームに頼る必要があります。
観察:
function foo() {
echo $bar;
}
スコープがない場合、上記の関数は何をしますか? どこ$bar
から来たの?それはどのような状態ですか?それも初期化されていますか?毎回チェックしないといけないの?これは維持できません。それは私たちに...
function foo($bar) {
echo $bar;
return 42;
}
変数$bar
は、関数の引数として明示的にこのスコープに入ります。この関数を見るだけで、それが機能する値がどこから来たのかは明らかです。次に、明示的に値を返します。呼び出し元は、関数がどの変数を処理するか、およびその戻り値がどこから来るかを確実に知ることができます。
$baz = 'baz';
$blarg = foo($baz);
$foo = 'bar';
$baz = function () use ($foo) {
echo $foo;
};
$baz();
無名関数は$foo
、周囲のスコープから明示的にインクルードします。これはグローバルスコープと同じではないことに注意してください。
global
前に述べたように、グローバル スコープはやや特殊であり、関数はそこから変数を明示的にインポートできます。
$foo = 'bar';
function baz() {
global $foo;
echo $foo;
$foo = 'baz';
}
この関数は、グローバル変数を使用および変更します$foo
。こんなことしないで! (自分が何をしているのか本当に本当に本当によくわかっている場合を除きます。その場合でも: やめてください!)
この関数の呼び出し元が見るのはこれだけです:
baz(); // outputs "bar"
unset($foo);
baz(); // no output, WTF?!
baz(); // outputs "baz", WTF?!?!!
この関数に副作用があるという兆候はありませんが、実際にはあります。一部の関数は変更を続け、何らかのグローバル状態を必要とするため、これは非常に簡単に絡み合った混乱になります。関数をステートレスにして、入力に対してのみ動作し、定義された出力を返す必要がありますが、何度呼び出してもかまいません。
可能な限り、グローバル スコープの使用を避ける必要があります。最も確実なのは、変数をグローバルスコープからローカルスコープに「プル」するべきではありません。