参照:変数スコープとは何ですか?どこからアクセスできる変数と「未定義変数」エラーとは何ですか?

168
deceze 2013-06-07 00:20.

注:これは、PHPで変数スコープを処理するための参照用の質問です。このパターンの複製として、このパターンに当てはまる多くの質問のいずれかを閉じてください。

PHPの「可変スコープ」とは何ですか?ある.phpファイルの変数は別の.phpファイルからアクセスできますか?「未定義の変数」エラーが発生することがあるのはなぜですか?

3 answers

188
deceze 2013-06-07 00:20.

「可変スコープ」とは何ですか?

変数の「スコープ」または「アクセス可能な場所」は限られています。アプリケーションのどこか$foo = 'bar';一度書いたからといって、アプリケーション内の他のどこ$fooからでも参照できるわけではありません。変数に$fooは、それが有効である特定のスコープがあり、同じスコープ内のコードのみが変数にアクセスできます。

PHPでスコープはどのように定義されていますか?

非常に単純です: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?!?!!

この機能に副作用があるという兆候はありませんが、副作用はあります。一部の関数は変更続け、グローバルな状態を必要とするため、これは非常に簡単に混乱します。関数をステートレスにし、入力のみに作用し、定義された出力を返すようにしますが、何度も呼び出します。

可能な限り、グローバルスコープの使用は避けてください。確かに、変数をグローバルスコープからローカルスコープに「プル」するべきではありません。

9
Alex Myznikov 2017-02-17 11:06.

関数のスコープ内で定義された変数に外部からアクセスすることはできませんが、その関数の完了後にそれらの値を使用できないことを意味するわけではありません。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すると、追加の回避策なしでこの単純なカウンターを構築できます。

静的変数のユースケース

  1. 関数の結果の呼び出しの間に値を格納します。
  2. 値をパラメーターとして渡す方法がない(または目的がない)ときに、再帰呼び出しの間に値を格納すること。
  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

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

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

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

後者では、実際には静的変数の代わりにクロージャを使用できます。何を使用するかは常に開発者が決定しますが、静的変数は再帰を処理するときに間違いなく役立ち、開発者が気付くに値することに注意してください。

2
miken32 2019-05-14 04:18.

既存のものと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-dataMIMEタイプを使用してHTTPPOSTリクエストで渡される値
  • $_FILESmultipart/form-data-MIMEタイプのHTTPPOSTリクエストで渡されたファイル
  • $_COOKIE -現在のリクエストで渡されたCookie
  • $_SESSION -PHPによって内部的に保存されたセッション変数
  • $_REQUEST-の典型的組み合わせ$_GET$_POST、時には$_COOKIES。内容は、のrequest_orderディレクティブによって決定されphp.iniます。
  • $_ENV -現在のスクリプトの環境変数

Related questions

MORE COOL STUFF

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは、夫に会ったとき、典型的な交際のアドバイスに逆らいました。

マイケルシーンが非営利の俳優である理由

マイケルシーンが非営利の俳優である理由

マイケルシーンは非営利の俳優ですが、それは正確にはどういう意味ですか?

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

特徴的なスターのコリン・エッグレスフィールドは、RomaDrama Liveでのスリル満点のファンとの出会いについて料理しました!加えて、大会での彼のINSPIREプログラム。

「たどりつけば」をオンラインでストリーミングできない理由

「たどりつけば」をオンラインでストリーミングできない理由

ノーザンエクスポージャーが90年代の最も人気のある番組の1つになった理由を確認するには、Blu-rayまたはDVDプレーヤーをほこりで払う必要があります。

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖は、世界で2番目に大きいボイリング湖です。そこにたどり着くまでのトレッキングは大変で長いですが、努力する価値は十分にあります。

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

サロンからのヘアトリミングや個人的な寄付は、油流出を吸収して環境を保護するのに役立つマットとして再利用できます。

ホワイトハウスの最も記憶に残る結婚式を見てください

ホワイトハウスの最も記憶に残る結婚式を見てください

過去200年以上の間にホワイトハウスで結婚したのはほんの数人です。彼らは誰でしたか、そしてそこで結婚式を獲得するために何が必要ですか?

今週のコミックコンですべての素晴らしいものに追いつく方法

今週のコミックコンですべての素晴らしいものに追いつく方法

サンディエゴコミックコンは今週開幕し、オタクのアナウンス、ポスター、予告編、お気に入りの番組や映画のからかいでいっぱいになります。SDCCは、コンベンションフロア全体の多くのパネルで行われているため、すべてに対応するのは難しい場合があります。

Googleの9千万ドルの和解はアプリ開発者にとってもGoogleにとっても勝利ですか?

Googleの9千万ドルの和解はアプリ開発者にとってもGoogleにとっても勝利ですか?

小さなアプリ開発者は金曜日に発表された法的な和解でグーグルから9千万ドルをこじ開けた。アップルとの同様の合意に続いて熱くなった。金曜日のブログ投稿で、Googleは、Androidメーカーが市場での優位性を悪用してPlayストア経由でのアプリ内購入に対して30%の料金を不当に請求したと主張するアプリ開発者との訴訟を解決するために、9千万ドルを支払うことに合意したと述べました。

RadioShackのTwitterはハッキングされていませんでした、それはただの暗号のサクラです

RadioShackのTwitterはハッキングされていませんでした、それはただの暗号のサクラです

今週、RadioShackのTwitterアカウントは、奇妙なものから完全にひどいものになりました。短い順序で、会社のフィード全体が、バイブレーター、「ビッグティット」(スペルミス)、有名人やその他の企業アカウントを荒らしているツイートなど、NSFW素材の真の山になりました。

ヒッグス粒子から10年後、物理学にとって次の大きなものは何ですか?

ヒッグス粒子から10年後、物理学にとって次の大きなものは何ですか?

大型ハドロン衝突型加速器のトンネル内にあるコンパクトミュオンソレノイド(CMS)検出器。2012年7月4日、CERNの科学者たちは、1960年代に最初に提案された素粒子であるヒッグス粒子の観測を確認しました。

Zendaya Wishes Boyfriend Tom Holland Happy Birthday with Cuddly Photo: He 'Makes Me the Happiest'

Zendaya Wishes Boyfriend Tom Holland Happy Birthday with Cuddly Photo: He 'Makes Me the Happiest'

Zendaya shared a sweet photo in honor of boyfriend Tom Holland's 26th birthday Wednesday

小さな女性:脳卒中を患った後に病院から解放されたアトランタのジューシーな赤ちゃん:「まだ癒し」

小さな女性:脳卒中を患った後に病院から解放されたアトランタのジューシーな赤ちゃん:「まだ癒し」

シーレン「Ms.JuicyBaby」ピアソンは、先月脳卒中で入院した後、「もう一度たくさんのことをする方法を学ばなければならない」ため、言語療法を受けていることを明らかにしました。

エマストーンは彼女のクリフサイドマリブビーチハウスを420万ドルでリストアップしています—中を見てください!

エマストーンは彼女のクリフサイドマリブビーチハウスを420万ドルでリストアップしています—中を見てください!

オスカー受賞者の世紀半ばの家には、3つのベッドルーム、2つのバス、オーシャンフロントの景色があります。

ジーニー・メイ・ジェンキンスは、母乳育児の経験の中で、彼女は「本当に、本当に落ち込んでいる」と言います

ジーニー・メイ・ジェンキンスは、母乳育児の経験の中で、彼女は「本当に、本当に落ち込んでいる」と言います

ジーニー・メイ・ジェンキンスは、生後4か月の娘、モナコに母乳育児をしていると語った。

Seguindo Todos os Protocolos (2022), de Fábio Leal

Seguindo Todos os Protocolos (2022), de Fábio Leal

Chico quer transar. Até aí, tudo bem.

多元宇宙—Junø

多元宇宙—Junø

チェーン間アカウントがJunoに登場します。異なるブロックチェーン間でスマートコントラクトの構成可能性と真の相互運用性を提供します。

#brand【ベター・コール・ソール!アメリカのテレビシリーズ「ブレイキング・バッド」に最高のビジネス例が隠されている】・・・ルールクリエイティブ

#brand【ベター・コール・ソール!アメリカのテレビシリーズ「ブレイキング・バッド」に最高のビジネス例が隠されている】・・・ルールクリエイティブ

1.ドラマを見た後、起業する考えはありますか?あなたのビジネスはボトルネックに遭遇しましたか?方向性がなくてわからない場合は、ドラマを追いかけて行くことを心からお勧めします。(?)ブラフではなく、最も完璧なビジネス例を隠すドラマがあります。2.ブレイキング・バッドとその弁護士ドラマ「ブレイキング・バッド」を見た友人たちは、演劇の中で、穏やかな表情で、弁護士のソウル・グッドマンに深く感銘を受けなければなりません。口を開けて、感覚の弱い傭兵の性格を持っています。道徳の面で、サル・グッドマンは無意識のうちに劇に欠かせない役割を果たし、彼自身のシリーズ「絶望的な弁護士」(ベター・コール・ソール)を生み出しました。ウェントウのテキストとビデオは、劇中のソウル・グッドマンのテレビコマーシャルです。製品(サービス)、競争戦略、市場ポジショニング、ブランド名、ターゲット顧客グループ、コミュニケーション軸から広告まで、サル・グッドマンの役割のビジネス設定は、「最低」と見なすことができる超超超超超超完全です。ブランドコミュニケーションのコスト」「変化」のモデル。なぜ?私の分析をご覧ください。3.ソウル・グッドマンの「事業戦略」1.基本情報ブランド名:Saul Goodman製品:法律相談サービス対象顧客:麻薬中毒、飲酒運転、事故など。法律知識の欠如は、一般的に公立弁護士にしか余裕がなく、真面目な弁護士も「特別な法律を持つ消費者」を避けます。恐れてはいけない「​​ニーズ」。コミュニケーションの主軸:この国のすべての男性、女性、子供は有罪判決を受けるまで無実だと思います。地域:アルバカーキ市スローガン:Thrallに電話したほうがいいです!(ベター・コール・ソール)広告:2つの可能性のある犯罪状況をシミュレートします+サウルの主張+サウルのスローガン2をより適切に呼び出します。

メインネットガイド— Arbitrum Odyssey Week 2

メインネットガイド— Arbitrum Odyssey Week 2

最新のアップデートを受け取るために私たちに従ってください。ニュースレター:https://www。

Language