注:これは、PHPで変数スコープを処理するための参照用の質問です。このパターンの複製として、このパターンに当てはまる多くの質問のいずれかを閉じてください。
PHPの「可変スコープ」とは何ですか?ある.phpファイルの変数は別の.phpファイルからアクセスできますか?「未定義の変数」エラーが発生することがあるのはなぜですか?
変数の「スコープ」または「アクセス可能な場所」は限られています。アプリケーションのどこかに$foo = 'bar';
一度書いたからといって、アプリケーション内の他のどこ$foo
からでも参照できるわけではありません。変数に$foo
は、それが有効である特定のスコープがあり、同じスコープ内のコードのみが変数にアクセスできます。
非常に単純です:PHPには関数スコープがあります。これは、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?!?!!
この機能に副作用があるという兆候はありませんが、副作用はあります。一部の関数は変更を続け、グローバルな状態を必要とするため、これは非常に簡単に混乱します。関数をステートレスにし、入力のみに作用し、定義された出力を返すようにしますが、何度も呼び出します。
可能な限り、グローバルスコープの使用は避けてください。確かに、変数をグローバルスコープからローカルスコープに「プル」するべきではありません。
関数のスコープ内で定義された変数に外部からアクセスすることはできませんが、その関数の完了後にそれらの値を使用できないことを意味するわけではありません。PHPには、static
静的メソッドとプロパティを定義するためにオブジェクト指向PHPで広く使用されているよく知られたキーワードがありますが、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
それ$counter
なしで定義した場合static
、毎回エコーされる値は$num
、関数に渡されるパラメーターと同じになります。を使用static
すると、追加の回避策なしでこの単純なカウンターを構築できます。
静的変数は、ローカル関数スコープにのみ存在します。定義されている関数の外部からアクセスすることはできません。したがって、その関数を次に呼び出すまで、値を変更しないでおくことができます。
静的変数は、スカラーまたはスカラー式としてのみ定義できます(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
これは、同じクラスのオブジェクトでのみ機能します。オブジェクトが異なるクラスからのものである場合(互いに拡張している場合でも)、静的変数の動作は期待どおりになります。
関数呼び出し間で値を保持する別の方法は、クロージャを使用することです。クロージャーはPHP5.3で導入されました。つまり、関数スコープ内の変数のセットへのアクセスを、それらにアクセスする唯一の方法となる別の無名関数に制限することができます。クロージャ変数に含まれていると、構造化プログラミングの「クラス定数」(値によってクロージャに渡された場合)や「プライベートプロパティ」(参照によって渡された場合)などのOOP概念を(多かれ少なかれうまく)模倣できます。
後者では、実際には静的変数の代わりにクロージャを使用できます。何を使用するかは常に開発者が決定しますが、静的変数は再帰を処理するときに間違いなく役立ち、開発者が気付くに値することに注意してください。
既存のものとPHPマニュアルはこれのほとんどを説明するのに素晴らしい仕事をしているので、私は質問に対する完全な答えを投稿しません。
しかし逃した一人の被験者は、であったスーパーグローバルなど、一般に使用される$_POST
、$_GET
、$_SESSION
、等が挙げられる。これらの変数はせずに、任意の範囲で、常に利用可能である配列でglobal
宣言。
たとえば、この関数は、PHPスクリプトを実行しているユーザーの名前を出力します。変数は問題なく関数で使用できます。
<?php
function test() {
echo $_ENV["user"];
}
「グローバルは悪い」という一般的なルールは、誤用しない限り、通常、PHPでは「グローバルは悪いがスーパーグローバルは大丈夫」に修正されています。(これらの変数はすべて書き込み可能であるため、本当にひどい場合は、依存性の注入を回避するために使用できます。)
これらの変数が存在することは保証されていません。管理者は、使用してそれらの一部またはすべてを無効にすることができvariables_order
ディレクティブではphp.ini
、これは一般的な動作ではありません。
現在のスーパーグローバルのリスト:
$GLOBALS
-現在のスクリプトのすべてのグローバル変数$_SERVER
-サーバーと実行環境に関する情報$_GET
-リクエストに使用されたHTTPメソッドに関係なく、URLのクエリ文字列で渡される値$_POST
-application/x-www-form-urlencoded
またはmultipart/form-data
MIMEタイプを使用してHTTPPOSTリクエストで渡される値$_FILES
multipart/form-data
-MIMEタイプのHTTPPOSTリクエストで渡されたファイル$_COOKIE
-現在のリクエストで渡されたCookie$_SESSION
-PHPによって内部的に保存されたセッション変数$_REQUEST
-の典型的組み合わせ$_GET
と$_POST
、時には$_COOKIES
。内容は、のrequest_order
ディレクティブによって決定されphp.ini
ます。$_ENV
-現在のスクリプトの環境変数Reba McEntire が息子の Shelby Blackstock と共有しているクリスマスの伝統について学びましょう。
メーガン・マークルとマライア・キャリーが自然な髪の上でどのように結合したかについて、メーガンの「アーキタイプ」ポッドキャストのエピソードで学びましょう.
ハリー王子が家族、特にチャールズ王とウィリアム王子との関係について望んでいると主張したある情報源を発見してください。
ワイノナ・ジャッドが、母親のナオミ・ジャッドが亡くなってから初めての感謝祭のお祝いを主催しているときに、彼女が今では家長であることをどのように認識したかを学びましょう.
Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?
The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!
ランボルギーニの創設者であるフェルッチオランボルギーニが100歳になるのは毎日ではありません(そうです、彼は死んでいて、まだ死んでいると思います。
Appleが自動車分野に参入するという噂はかなり前から渦巻いており、AppleウォッチャーがSixtyEight Researchという会社がAppleの自動車研究開発のシェル会社である可能性が高いと判断したとき、その渦巻きは本当に渦巻いた。また、会社が購入した車は1台だけであることが知られており、その車はAppleが何を考えているかについての手がかりでいっぱいになる可能性があることも伝えています。
太陽系の外側にある架空の大きな物体である惑星Xの探索は、何十年にもわたって人間を魅了してきました。その検索の最新の章は、地球の10倍の大きさで、公転周期が15であるほど遠くにある惑星を指しています。
カムニュートンは昨日、簡単な265ヤードと3回のタッチダウンでファルコンズを引き裂き、別の素晴らしいゲームをしました。その日のハイライトは、上のタッチダウンスローでした。これは、視聴するたびにばかげているだけです。
ロシアのフィギュアスケーター、カミラ・バリエバが関与したドーピング事件が整理されているため、チームは2022年北京冬季オリンピックで獲得したメダルを待っています。
何千人ものAmazonの買い物客がMulberry Silk Pillowcaseを推奨しており、現在販売中. シルクの枕カバーにはいくつかの色があり、髪を柔らかく肌を透明に保ちます。Amazonで最大46%オフになっている間にシルクの枕カバーを購入してください
ラファイエット警察署は、「不審な男性が女性に近づいた」という複数の苦情を受けて、12 月にパデュー大学の教授の捜査を開始しました。
私たちの周りの世界と同じように、言語は常に変化しています。以前の時代では、言語の変化は数年または数十年にわたって発生していましたが、現在では数日または数時間で変化する可能性があります。
認知症を患っている 91 歳のアジア人女性が最近、47 番街のアウター サンセット地区でロメオ ロレンゾ パーハムに襲われました。伝えられるところによると、被害者はサンフランシスコの通りを歩いていたところ、容疑者に近づき、攻撃を受け、暴行を受けました。
“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.
人々にチャンスを与えることは、人生で少し遅すぎると私は信じています。寛大に。