PHP変数のスコープ

伊谢尔伦
伊谢尔伦オリジナル
2016-11-24 13:47:081446ブラウズ

変数のスコープは、変数が定義されているコンテキスト (つまり、その有効スコープ) です。ほとんどの PHP 変数にはスコープが 1 つだけあります。この単一スコープ スパンには、 include および require によって導入されたファイルも含まれます。例:

<?php
    $a = 1;
    include &#39;b.inc&#39;;
?>

この変数 $a は、インクルード ファイル b.inc で有効になります。ただし、ユーザー定義関数では、ローカル関数スコープが導入されます。関数内で使用される変数は、デフォルトではローカル関数のスコープに制限されます。例:

<?php
    $a = 1; /* global scope */
    function Test()
    {
        echo $a; /* reference to local scope variable */
    }
    Test();
?>

echo ステートメントは変数 $a のローカル バージョンを参照しており、このスコープ内の値が割り当てられていないため、このスクリプトは出力を生成しません。 PHP のグローバル変数は C 言語とは少し異なることに気づくかもしれません。C 言語では、ローカル変数によってオーバーライドされない限り、グローバル変数は関数内で自動的に有効になります。これにより問題が発生する可能性があり、誰かが誤ってグローバル変数を変更してしまう可能性があります。 PHP のグローバル変数を関数で使用する場合は、グローバル変数を宣言する必要があります。

グローバルキーワード

まず、グローバルの使用例:

例 #1 グローバルの使用

<?php
    $a = 1;
    $b = 2;
    function Sum()
    {
        global $a, $b;
        $b = $a + $b;
    }
    Sum();
    echo $b;
?>

上記のスクリプトの出力は「3」になります。グローバル変数 $a および $b が関数内で宣言されると、いずれかの変数へのすべての参照がそのグローバル バージョンを指します。 PHP では、関数が宣言できるグローバル変数の最大数に制限はありません。

グローバル スコープ内の変数にアクセスする 2 番目の方法は、特別な PHP カスタム $GLOBALS 配列を使用することです。前の例は次のように記述できます:

例 #2 global の代わりに $GLOBALS を使用します

<?php
    $a = 1;
    $b = 2;
    function Sum()
    {
        $GLOBALS[&#39;b&#39;] = $GLOBALS[&#39;a&#39;] + $GLOBALS[&#39;b&#39;];
    }
    Sum();
    echo $b;
?>

$GLOBALS は連想配列であり、各変数は要素であり、キー名は変数名に対応し、値は変数の内容。 $GLOBALS はスーパーグローバル変数であるため、$GLOBALS はグローバル スコープ内に存在します。次の例は、スーパーグローバル変数の有用性を示しています。

例 #3 スーパーグローバル変数とスコープを示す例

<?php
    function test_global()
    {
        // 大多数的预定义变量并不 "super",它们需要用 &#39;global&#39; 关键字来使它们在函数的本地区域中有效。
        global $HTTP_POST_VARS;
        echo $HTTP_POST_VARS[&#39;name&#39;];
        // Superglobals 在任何范围内都有效,它们并不需要 &#39;global&#39; 声明。Superglobals 是在 PHP 4.1.0 引入的。
        echo $_POST[&#39;name&#39;];
    }
?>

静的変数の使用

変数スコープのもう 1 つの重要な機能は、静的変数です。静的変数はローカル関数スコープ内にのみ存在しますが、プログラムの実行がこのスコープを離れても、その値は失われません。次の例を見てください:

例 #4 静的変数を必要とする例を示します

<?php
    function Test()
    {
        $a = 0;
        echo $a;
        $a++;
    }
?>

この関数は、呼び出されるたびに $a の値を 0 に設定し、0 を出力するため、あまり役に立ちません。変数を 1 つインクリメントする $a++ は、この関数が終了すると変数 $a が存在しなくなるため、効果がありません。現在のカウント値を失わないカウント関数を作成するには、変数 $a を静的として定義します:

例 #5 静的変数の使用例

<?php
    function test()
    {
        static $a = 0;
        echo $a;
        $a++;
    }
?>

これで、変数 $a は test( が呼び出された場合にのみ使用されます)初めて ) 関数が初期化され、それ以降 test() 関数が呼び出されるたびに $a の値が出力され、1 ずつ増加します。

静的変数は、再帰関数を処理する方法も提供します。再帰関数は、それ自体を呼び出す関数です。再帰関数を作成するときは、無限に再帰する可能性があるので注意してください。再帰を終了する適切な方法があることを確認する必要があります。次の単純な関数は、静的変数 $count を使用して再帰的に 10 までカウントし、いつ停止するかを決定します:

例 #6 静的変数と再帰関数

<?php
    function test()
    {
        static $count = 0;
        $count++;
        echo $count;
        if ($count < 10) {
            test();
        }
        $count--;
    }
?>

静的変数は、上の例のように宣言できます。これを宣言内の式の結果に代入すると、解析エラーが発生します。

例 #7 静的変数の宣言

<?php
    function foo(){
        static $int = 0; // correct
        static $int = 1+2; // wrong (as it is an expression)
        static $int = sqrt(121); // wrong (as it is an expression too)
        $int++;
        echo $int;
    }
?>

静的宣言はコンパイル時に解決されます。

関数の外で global キーワードを使用することに問題はありません。関数内にファイルを含める場合に使用できます。

グローバル変数と静的変数への参照

PHP4 を駆動する Zend エンジン 1 世代では、変数の静的定義とグローバル定義は参照の形式で実装されます。たとえば、関数スコープ内の global ステートメントを使用してインポートされた真のグローバル変数は、実際にグローバル変数への参照を確立します。これは、次の例に示すように、予期しない動作を引き起こす可能性があります:

<?php
    function test_global_ref() {
        global $obj;
        $obj = &new stdclass;
    }
    function test_global_noref() {
        global $obj;
        $obj = new stdclass;
    }
    test_global_ref();
    var_dump($obj);
    test_global_noref();
    var_dump($obj);
?>

上記のルーチンは出力します:

NULL
object(stdClass)(0) {}

同様の動作は、静的ステートメントにも適用されます。参照は静的に保存されません:

<?php
    function &get_instance_ref() {
        static $obj;
        echo &#39;Static object: &#39;;
        var_dump($obj);
        if (!isset($obj)) {
           // 将一个引用赋值给静态变量
           $obj = &new stdclass;
        }
        $obj->property++;
        return $obj;
    }
    function &get_instance_noref() {
        static $obj;
        echo &#39;Static object: &#39;;
        var_dump($obj);
        if (!isset($obj)) {
            // 将一个对象赋值给静态变量
            $obj = new stdclass;
        }
        $obj->property++;
        return $obj;
    }
    $obj1 = get_instance_ref();
    $still_obj1 = get_instance_ref();
    echo "\n";
    $obj2 = get_instance_noref();
    $still_obj2 = get_instance_noref();
?>

上記のルーチンは次のように出力します:

  Static object: NULL
    Static object: NULL
    Static object: NULL
    Static object: object(stdClass)(1) {
        ["property"]=>int(1)
    }

上記の例は、参照が静的変数に割り当てられるとき、&get_instance_ref() 関数が 2 回目にライブで呼び出されるとき、その値は記憶されないことを示しています。 。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
前の記事:PHP変数変数次の記事:PHP変数変数