三陸牡蠣復興支援プロジェクト「SAVE SANRIKU OYSTER」



変数

へ、変数ぅ??

変数とは何ぞや。前回の「PHPとは」のページで記したサンプル内の「echo "  <em>hello,HODENASU!!</em>";」は、「『<em>hello,HODENASU!!</em>』と出力しろ。」という命令であると書きましたが、これを分解すると、「echo」と「"  <em>hello,HODENASU!!</em>"」と「;」の3つに分ける事が出来ます。これら3つが何なのかですが、


まず1つ目の「echo」は、「パラメータ(引数)に指定した文字列を出力する」という命令、PHPの言語構造です。


2つ目の「"  <em>hello,HODENASU!!</em>"」は、「echo」のパラメータ。


3つ目の「;」は、「1つの文の終わりを告げるもの」です。


で、ここで問題になるのが2つ目の「パラメータ」です。今回のサンプルでは、パラメータに二重引用符「"(ダブルクォーテーション)」で囲まれた文字列(「文字列リテラル(リテラルとは、具体的な値の事)」という)を指定しました。これを踏まえて次のサンプルをご覧下さい。

<html>
<body>
<?php
    echo "  <em>hello,HODENASU!!</em>";
    echo "  <em>hello,HODENASU!!</em>";
    echo "  <em>hello,HODENASU!!</em>";
    echo "  <em>hello,HODENASU!!</em>";
    echo "  <em>hello,HODENASU!!</em>";
?>
</body>
</html>

このサンプルは、見たまんま、「『<em>hello,HODENASU!!</em>』と出力。」×5 という処理になります。「『<em>hello,HODENASU!!</em>』と出力。」という処理を5回したいんです。が、もし、『HODENASU』を『HODENEGASU』のように綴りを間違えてしまったら、5回『HODENEGASU』と出力される事になり、修正する場合、5箇所修正する羽目になります。

「・・・。アレェ!?これって、わざわざPHP使う必要無くねぇ!?オイ!この野郎!この前、「PHPで動的にHTMLを生成します」なんて事言ってたくせして、全然動的でもなんでもねーじゃねーが!」
「お客様!それは、お客様がお書きになったスクリプトの問題です!」
「どういう事だこの野郎!そもそも動的って何なんだわかんね―よ!」
「お客様!前回のページに書いてあります!衝動的に電話するのはお止め下さい!」
「動的だけにぃ」
「夕空が、セピア色に見えた。。。」

前回、「PHPで動的にHTMLを生成する」なんて書きましたがこのサンプルでは建前上動的に生成はしますが実質的には出来合いのHTMLを表示するのと変わりありません。

ここで登場するのが、変数です。

で、変数って何なの?

変数はね、何でも入る魔法の箱なんだぞぉ

「ウソつけ。」まず、下記のサンプルをご覧下さい。

<html>
<body>
<?php
    $hode = "  <em>hello,HODENASU!!</em>";

    echo $hode;
    echo $hode;
    echo $hode;
    echo $hode;
    echo $hode;
?>
</body>
</html>

新しく、「$hode = "  <em>hello,HODENASU!!</em>";」なんてのが登場しました。この中の「$hode」が変数です。で、この新しく登場した一文の意味は、「変数$hodeに『  <em>hello,HODENASU!!</em>』という文字列を代入する」です。この一文の中の「=(イコール)」は、「代入演算子(「演算子」のページでも解説)」というもので、「第1オペランド(左辺の被演算子)に、第2オペランド(右辺の被演算子)の値を格納し、格納された値を返す(「返す」という言葉の意味は「関数」のページで解説)」という働きをします。「等しい」という意味ではありません。この代入により、「変数$hode」は『  <em>hello,HODENASU!!</em>』という文字列(値)を持ち、今後この変数を参照(使う事)すると、変数内の値(文字列)を得られるようになります。よって、上のサンプルは、「変数$hodeの値の『<em>hello,HODENASU!!</em>』を出力。」×5 という処理になります。

なお、新しく変数を登場させ値を代入する事を、「変数を定義する」と言います。

変数に名前を付けましょう(変数の命名規則)

颯爽と登場した変数ですが、この変数には名前をつける必要があり、その名前の付け方には決まり事があります。まず、ごらんの通り、変数は「$(ドルマーク)」から始まり、その後ろにある「hode」が変数の名前、「変数名」です。で、変数名を決めるにあたっては、以下の事に注意する必要があります。

変数名の命名規則
  • 大文字と小文字は区別される。つまり、「$HODE」と「$hode」は全く違うものとして扱われる。
  • 変数名は、アルファベットもしくは「_(アンダースコア)」から始まり、任意の数のアルファベットもしくは数字もしくはアンダースコアが続く。「$200X」は、数字で始まっているので無効。有効な例:「$_200X」

変数に格納できる値は1つのみ

まず、下記のサンプルをご覧下さい。

<html>
<body>
<?php
    $hode = 2004;
    $hode = "  <em>hello,HODENASU!!</em>";
    $hode = "  <em>Good By!!!</em>";

    echo $hode;
?>
</body>
</html>

結果は以下の通り。

Good By!!!

さて、「変数$hode」に格納(代入)したはずの「2004」と「" <em>hello,HODENASU!!</em>"」は何処へ行ってしまったのでしょうか?答えは、消えて無くなりました。すでに値が格納されている変数に、再び値を代入しようとすると、元の値がクリアされた上で、新しい値が格納されます。要するに上書きされるわけです。

変数のスコープ

グローバル変数とローカル変数

変数には、「スコープ」というものが存在します。スコープとは、「変数を参照することが出来る範囲」の事です。

<html>
<body>
<?php
    $hode = 100;

    function test(){
        $hode = 200;
        $nda = 300;
        return $hode;
    }
    
    echo test();
    echo "<hr />";
    echo $hode;
    echo "<hr />";
    echo $nda;
?>
</body>
</html>

このサンプルの意味は、


「変数$hode」を定義して100を代入。


「関数(「関数」のページで解説)test()」を定義。


「関数test()」を実行し、その返り値(「関数」のページで解説)を出力。


「<hr />」を出力。


「変数$hode」の値を出力。


「<hr />」を出力。


「変数$nda」の値を出力。


で、今回のサンプルの結果は以下のようになると予想されます。

200

200
300

ところがどっこい、結果は以下のようになります。

200

100

「変数$hode」の値は「100」のままで、「変数$nda」の値は出力されていません。この結果からも解かるように、関数の中からは関数の外の変数は参照出来ず、逆に、関数の外から関数の中の変数は参照出来ません。そして、これらの変数の事をそれぞれ以下のように言います。

グローバルスコープとローカルスコープ
  • 関数外で定義された変数を「グローバル変数」といい、「グローバルスコープ」に存在します。
  • 関数内で定義された変数を「ローカル変数」といい、「ローカルスコープ」に存在します。

このように、変数の参照範囲は制限されているのですが、関数内で関数外の変数(グローバル変数)を参照したい場合もあります。そんな時は、関数内で「修正子global」を使う事で、グローバル変数をグローバルとして宣言(何か変だな…)することによって、参照可能になります。また、「スーパーグローバル変数(PHP側で自動的に定義される連想配列(「配列」ページで解説))$GLOBALS["グローバル変数名"]」で参照する事も出来ます。

「修正子global」で宣言する際、「,(コンマ)」で区切って複数の変数を同時に宣言する事も出来ます。また、元々グローバルに存在しない変数を宣言して、その関数がコール(実行する事)された時点で定義させる事も出来ます。

<html>
<body>
<?php
    $hode = 100;
    $nasu = 150;

    function test(){
        global $hode, $nda;
        $hode = 200;
        $GLOBALS["nasu"] = 250;
        $nda = 300;
    }
    
    test();
    echo $hode;
    echo "<hr />";
    echo $nasu;
    echo "<hr />";
    echo $nda;
?>
</body>
</html>

この結果は以下のようになります。

200

250
300

静的(スタティック)変数

「疲れたんですけど。」 もう一息。

関数内から関数外の変数を参照できるようにはなり、今度はその逆もしてみたいと思うのが人の常(?)でしょうが、残念ながら出来ません。出来ないんです。出来る必要が無いんです。そもそも関数と言うものは(「関数」のページで解説)値を受け取って、その受け取った値を加工して値を返すのが主な任務なわけで。つまり例えると、関数は野菜ジュースを生産する工場です。


「・・・。オイ!この野郎!「関数は野菜ジュースを生産する工場です。」ってよ!意味解かんねーよ!例え下手にも程があるんじゃね―のかよ!」
「お客様!まだ話が終ってません!焦らずに説明をお聞きください!」
「オチが、思い浮かばなかった。。。」


よく分かりませんが、野菜ジュースは、決まった材料を決まった分量で決まったタイミングで加工して作られていると思います。一度作り方を決めてしまえば、後は生産ラインを回し続け、不測の事態でも発生しない限り、野菜ジュースを作り続けると思います。が、工場内に、関係者ではない外部の人間が侵入して、リンゴが入っているべきところに、勝手にカレーのルーを混入したらどうでしょうか。野菜ジュースのパックの中身は、とってもヘルシーなカレーになってしまいます。それはそれで良いのかも知れませんが(なわけない)、野菜ジュース工場の役目は野菜ジュースを作ることであり野菜カレーを作る事ではありません。・・・。説明終わり。

で、ここで解説する「静的(スタティック)変数」ですが、これは、PHPのマニュアルによると「スタティック変数は、再帰関数を実現する1つの手段として使用される。再帰関数は、自分自身をコールする関数。」とあります。これについてちゃちゃっと解説して、変数については終わりにします。ちなみに、静的変数の「静的」の意味は「固定的な」という意味で、ここでは、「既に定義された変数を再び定義しない」という意味になります。

<html>
<body>
<?php
    function test(){
        $a = 0;
        $a = $a + 1;
        echo $a;
        echo "<br />";
    }
    function test2(){
        static $a = 0;
        $a = $a + 1;
        echo $a;
        echo "<br />";
    }
    
    test();
    test();
    test();
    
    echo "<hr />";
    
    test2();
    test2();
    test2();
?>
</body>
</html>

このサンプルの結果は以下のようになります。

1
1
1

1 2 3

今回のサンプルでは、2つの似た様な関数を定義し、それぞれ3回ずつ呼び出しています。2つの関数では共通して、最初に「変数$a」を定義し、「0」をセットしています。1つ目の関数では呼び出される度にセットされるので、出力されるのは毎回「1」になります。しかし、2つ目の関数では「修正子static」を使う事によって、一度定義された変数は再定義されず、前回呼び出されて関数の処理が終了した時点の値を保持し、それを使用しています。

「修正子static」を使って新しく静的変数を導入する場合、必ずしもそこで値を代入する必要はありません。単に「static $a;」のように書く事も出来ます。ちなみにこの場合「定義」とは言わず「宣言」と言います。また、静的変数の定義時には幾つか制限があります。静的変数の定義時には演算子(「演算子」のページで解説)や関数(「関数」のページで解説)を使用する事が出来ません。また、変数から代入する事も出来ません。

<html>
<body>
<?php
    function test_ok(){
        static $a;
        static $b = 0
        return $b;
    }
    
    function test_ng(){
        $a = 0;
        static $b = $a;
        static $b = 1 + 2;
        static $b = test_ok();
    }
?>
</body>
</html>

このサンプルでは、2つの関数を定義しています。「関数test_ok()」の方は問題ありませんが、「関数test_ng()」の方は文法的な誤りがあるためにエラーが発生してしまいます。

最後に、再帰関数(関数内で自分自身を呼び出す関数)のサンプルを。。。

<html>
<body>
<?php
    function test(){
        static $a = 0;
        $a = $a + 1;
        echo $a;
        echo "<br />";
        if($a < 3){
            test();
        }
        $a = $a - 1;
    }
    
    test();
    echo "<hr />";
    test();
?>
</body>
</html>

結果やいかに。

1
2
3

1 2 3

何故このような結果になったのか、箇条書きで追って見ましょう。なお、サンプル中の「if(){}」については「制御構造」のページで解説。

  1. 「関数test()」を呼び出し(1回目)。
  2. 「スタティック変数$a」定義。
  3. $a」に「1」加算で「1」に。「1」を出力。
  4. $a」が「3」未満なので「関数test()」(自分自身)を呼び出す(再帰1回目)。
  5. $a」に「1」加算で「2」に。「2」を出力。
  6. $a」が「3」未満なので「関数test()」(自分自身)を呼び出す(再帰2回目)。
  7. $a」に「1」加算で「3」に。「3」を出力。
  8. $a」が「3」未満ではないのでスキップ。
  9. $a」から「1」減算で「2」に(再帰2回目の文)。
  10. $a」から「1」減算で「1」に(再帰1回目の文)。
  11. $a」から「1」減算で「0」に(1回目の文)。
  12. 「関数test()」を呼び出し(2回目)。
  13. 以下、同じ。

ふぅ。

可変変数

では最後に(終ったんじゃねーのか…)、可変変数をダーっと解説して終ります。

<html>
<body>
<?php
    $kahen = "gasu";
    $gasu  = "gasuka";
    echo $$kahen;
?>
</body>
</html>

結果やいかに。

gasuka

今回のサンプルでは、「変数$kahen」に文字列「"gasu"」を、「変数$gasu」に文字列「"gasuka"」をセット。そして、「謎の変数$$kahen」を出力。結果、「変数$gasu」の値、「gasuka」が表示されました。

まず、「謎の変数$$kahen」ですが、これはタイプミスではありません。「謎の変数$$kahen」の「$kahen」の部分。これは「変数$kahen」であり、値に文字列「"gasu"」を持っています。その値の頭に「$」を付けると、何と言う事でしょう、「謎の変数$$kahen」は「変数$gasu」に姿を変えてしまいました。匠の優しさを感じますね。結果、「gasuka」が出力されるわけです。おしまい。

おさらいと予告

これで変数の解説は終り、と思わせといて実は変数についてはまだ覚える事があります。が、それはページを改めて解説致します。

変数とは

  • 変数は、文字列から数値、その他これから登場する色んなものが何でもかんでも入ってしまう魔法の箱の様なもの。
  • 変数の名前の頭には「$(ドルマーク)」を付ける。変数の名前、変数名には、命名規則がある。
  • 既に値が格納された変数に再び値を代入しようとすると、元の値はクリアされた上で新たに値が格納される。
  • 変数には、定義された場所によって、参照できる範囲に制限がある。
  • スタティック変数は、関数内で一度定義されると、次に呼ばれた時からは保持した値を使う。
  • 変数名には、文字列を持った変数を使う事が出来る(可変変数)。

制御するのじゃ

次回は、プログラミングの核である「制御構造」を解説します。制御構造を簡単に説明すると、「処理を制御する構造」ってそのまんま。。。「何かしらの処理をさせたい時に、その処理を実現するために作成するスクリプトを記述する仕組み」ですかね?この制御構造には、主に「if」、「for」、「while」等があり、これらは「もし○○なら××」や「○○の間××」といった処理を制御する働きを持ちます。

作成日:2004年03月11日 最終更新日:2004年05月16日
【印刷モード風モード で表示】