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



変数2

ここでは、「変数」のページで解説し切れなかった、変数の残りの部分、「定義済みの変数」と「リファレンス」について解説します。

定義済みの変数

PHPでは、スクリプトにアクセスした時点で、幾つかの変数が自動的に定義されます。これらの変数は「スーパーグローバル変数」と呼ばれる連想配列で「$_SERVER['SERVER_NAME']」の様に格納されます。

この「スーパーグローバル変数」は、“スーパー”と言うだけあって、どこからでもアクセス出来ます。関数内からでも、グローバル変数を関数内で参照する際に使う「global修正子」を使うことなく参照出来ます。スーパーグローバル変数には、次の9つがあります。

$GLOBALS

スクリプトのグローバルスコープの中で利用可能な全ての変数(「$_SERVER」等のスーパーグローバル変数も含む)へのリファレンス(下の方の「リファレンス」で解説)を格納。配列のキーには、各変数名がセットされます。例えば、「$hode = "HODENASU!!";」と定義された変数があれば、それを「$GLOBALS['hode']」でも参照出来ます。

このスーパーグローバル変数だけ、変数名が「_(アンダーバー)」で始まっていない事に注意。

$_SERVER

WEBサーバーや実行中のスクリプトに関する情報が格納されます。配列のキーに指定した文字列によって、様々な情報を得る事が出来ます。例えば、「$_SERVER['PHP_SELF']」には「現在実行中のスクリプトの、ファイル名を含めたドキュメントルートからの相対パス」が、「$_SERVER['SERVER_NAME']」には「スクリプトが実行されているサーバのホスト名(ドメイン名)」が、「$_SERVER['REMOTE_ADDR']」には「スクリプトにアクセスしているユーザーのIPアドレス」が格納されます。他にも色々ありますが、詳しくは本家のマニュアルをご参照下さい。

$_GET

フォームなどから「HTTP GET」で送信された値が格納されます。例えば、「http://www.shigeweb.jp/?hode=HODENASU」と送信された場合、それを「$_GET['hode']」で参照出来ます。

$_POST

フォームなどから「HTTP POST」で送信された値が格納されます。例えば、「<input type="hidden" name="hode" value="HODENASU" />」が送信された場合、それを「$_POST['hode']」で参照出来ます。

$_COOKIE

そのページに対応した「HTTP Cookie」が格納されます。例えば、「hode=HODENASU」というCookieがセットされていれば、それを「$_COOKIE['hode']」で参照出来ます。

ちなみに、Cookieの送信は以下のように行います。

<?php
    $hode = "HODENASU!!";
    setcookie('hode', $hode, time() + 3600);
?>

ブラウザにCookieが送信され、ブラウザの種類によって以下のような情報(クッキー名とその値、有効期限等の文字列情報)がPCに記録されます(Cookieが無効に設定されている場合は保存されません)。

...
...	hode	HODENASU!!	...
...

上の例の場合、1時間以内に同ページにアクセスすれば、以下の記述でCookieを得られます。

<?php
    echo $_COOKIE['hode'];
    
    /* output
    HODENASU!!
    */
?>
$_FILES

フォームの「HTTP POST ファイルアップロード」によって送信された(されようとしている)ファイルに関する情報が二次元配列で格納されます。例えば、HTMLで「type」属性が「file」のフォーム部品に、更に「name」属性に「hode_file」と名前を付けたフォームからファイルの送信を試みると、
$_FILES['hode_file']['name']」、
$_FILES['hode_file']['type']」、
$_FILES['hode_file']['tmp_name']」、
$_FILES['hode_file']['error']」、
$_FILES['hode_file']['size']
という5つの要素を持った配列を生成します。詳細についてはセクションを改めて解説したいと思います。

$_ENV

この配列には、「環境変数」というものが格納されます。これはサーバの設定等によって得られる値が変わってきます。OSに関する情報だったり、観覧者の環境に関する事だったり、又全く何も得る事が出来ない場合もあります。

$_REQUEST

この配列には、「$_GET」、「$_POST」、「$_COOKIE」、「$_FILES」の値が格納されます。例えば、「http://www.shigeweb.jp/?hode=HODENASU」と送信された場合、それを「$_REQUEST['hode']」でも参照出来ます。

$_SESSION

この配列には、「セッション」に関する情報が格納されます。セッションについてはセクションを改めて解説したいと思います。

リファレンス

「配列」のページで『値は別な所にあり、「どの「手」にどの「値」を」という感じで対応させている』と書きましたが、変数においても同じで、変数名は値に対応しているのであって、変数が値を占有しているわけではありません。この、変数名の値への対応を「リファレンス」と言います。

この事は、ある変数の値を別の名前の変数でも参照できる事を意味します。

ある変数「A」の値を別の名前の変数「B」で参照するには、変数「A」に値を対応させたように、その値への対応を変数「B」にも行う事で、2つの変数は共通の値へのリファレンスを保持し、これによって参照出来るようになります。以下にその方法を示したサンプルと結果を。

<?php
    $hode = "HODENASU!!";
    $nasu =& $hode;
    
    echo $hode."<br />";
    echo $nasu;
    
    echo "<hr />";
    
    $hode = "ODAZUMOCCO...";
    
    echo $hode."<br />";
    echo $nasu;
    
    echo "<hr />";
    
    $nasu = "APETOPE";
    
    echo $hode."<br />";
    echo $nasu;
    
    echo "<hr />";
    
    unset($hode);
    
    echo '$hode : '.$hode."<br />";
    echo '$nasu : '.$nasu;
?>
HODENASU!!
HODENASU!!

ODAZUMOCCO... ODAZUMOCCO...
APETOPE APETOPE
$hode : $nasu : APETOPE

まず、「変数$hode」に「"HODENASU!!"」を代入。

その次に「$nasu =& $hode;」なる一文があります。一見、「変数$nasu」に「変数$hode」の値を代入しているようにも見えますが、「&(アンパサンド)」なるものがあり、通常の代入ではないと判ります。

この「&演算子」は、『左辺の変数に右辺の「値」を格納する』という代入演算子に、『左辺の変数に右辺の変数と共通の「リファレンス」をセットする』という機能を持たせるものです。

結果、「変数$nasu」は「変数$hode」と共通のリファレンスを持つため、「変数$hode」の値を変更して、「変数$nasu」を参照すると、参照先の値が変更されているのがわかります。

また、その逆に「変数$nasu」の値を変更して、「変数$hode」を参照した場合でも、参照先の値が変更されているのがわかります。

最後に、「変数$hode」をアンセット(「unset()」関数は、「指定した変数を破棄する」関数です)してみました。もはや存在しない「変数$hode」は出力されず、「変数$nasu」は出力されています。この結果を見ると、「変数$nasu」は「変数$hode」の場所を覚えていたのではなく、「変数$hode」に格納されていた値の場所を覚えていた事が解かります。

リファレンス渡し

コールする関数に、コール元の変数のリファレンスを渡す事も出来ます。以下に、その方法を示したサンプルと結果を。

<?php
    function func(&$ref){
        echo $ref."<br />";
        $ref = "HODENASU!!";
    }
    
    $var = "NDA!";
    
    func($var);
    
    echo $var;
?>
NDA!
HODENASU!!

関数「func()」は、関数内の変数(要するにローカル変数)「$ref」に「"HODENASU!!"」を(無意味に)代入してるようにも見えますが、仮引数の部分が「&$ref」となっています。この場合、関数内のローカル変数「$ref」には、実引数に指定した変数へのリファレンスが自動的にセットされます。

よって、関数内のローカル変数「$ref」は引数に指定した変数「$var」へのリファレンスを持つことになり、「関数のローカル変数$ref」へ代入した値は「変数$var」でも参照できるようになります。

当然、この場合の関数が想定する実引数は変数へのリファレンスであるので、引数に変数以外のものを指定するとエラーになります。

リファレンスを返す

関数のコール時に変数へのリファレンスを渡す事が出来ましたが、逆に、関数が変数へのリファレンスを返す事も出来ます。以下に、その方法を示したサンプルと結果を。

<?php
    $hode = "HODENASU!!";

    function &get_var($arg){
        global $$arg;
        if(isset($$arg)){
            return $$arg;
        }else{
            return "not exists...";
        }
    }
    
    $var = &get_var("hode");
    echo $var."<hr />";
    
    $var = "NDA";
    
    $var = &get_var("hode");
    echo $var."<hr />";
    
    $var = &get_var("nasu");
    echo $var;
?>
HODENASU!!

NDA
not exists...

関数「get_var()」は、『受け取った値(可変変数用の文字列)の名前を持ったグローバル変数が存在すればその変数の値を、存在しなければ文字列の「"not exists..."」を返す』というもの(の様に見えますが実際は違います)です。

が、関数名の前(定義部とコール部で)に「&演算子」があります。この場合、関数が返す値は、変数の値ではなく変数へのリファレンスです。

よって、「変数$var」には、関数「get_var()」によって返された変数へのリファレンス(引数に指定した名前の変数が存在すれば)が代入されます。

ちなみに、変数へのリファレンスを返させたい場合は、関数の定義部とコール部の両方で、関数名の前に「&演算子」を置かなくてはなりませんが、どちらか一方の「&演算子」を省略した場合、エラーにはならず通常の動作になります。

また、サンプルを見れば解かる通り、関数が返すものが変数以外のもの(ここでは文字列)である場合は、そのままそれが返されます。

で、リファレンスってどんな時に使うの?

ある変数「例えば$hode」の中身をどうにかしたい(一時的にではなく完全に)時に、どうにかする関数を(変数を渡して)使用する場合、使用する関数の仮引数が「function test($var){}」となっていると、仮引数である「変数$var」には、コールした際に渡した変数の値がコピーされます。

この関数内では、「ローカル変数$var」の値をどうにかして、その値を「return文」で返し、「変数$hode」に代入する事になります。これでも特に問題ありませんが、リファレンスを使用すれば効率よく、無駄を省いて処理させる事が出来ます。以下に、その方法を示したサンプルと結果を。

<?php
    #「(文字列が格納された)変数の前後にタグを追記する」関数の定義
    
    # 通常バージョン #
    
    function add_tag($str, $tag){
        $str = "<{$tag}>".$str."</{$tag}>";
        return $str;
    }
    
    # リファレンスバージョン #
    
    function add_tag_ref(&$str, $tag){
        $str = "<{$tag}>".$str."</{$tag}>";
    }
    
    $hode = "HODENASU!!";
    
    echo $hode;
    
    $hode = add_tag($hode, "em"); //通常バージョン
    
    echo $hode;
    
    $hode = "HODENASU!!";
    
    add_tag_ref($hode, "em");     //リファレンスバージョン
    
    echo $hode;
?>
HODENASU!!<em>HODENASU!!</em><em>HODENASU!!</em>

微妙です。

リファレンスバージョンの方が、仮引数に実引数の値がコピーされない分、効率的です。多分。以上。

おさらいと予告

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

定義済みの変数、リファレンス

  • スクリプトにアクセスした時点で自動的に定義される変数は、「スーパーグローバル変数」という連想配列に格納される。また、この変数には何処からでもアクセス出来る。
  • 変数は値ではなく値へのリファレンスを持っているだけなので、「&演算子」を使ってリファレンスをコピーすれば異なる変数から1つの値を参照する事が出来る。
  • 関数の仮引数の前に「&演算子」を置くと、仮引数(ローカル変数)には自動的に指定された変数へのリファレンスがセットされる。この場合の関数には変数以外のものを指定する事は出来ない。
  • 関数名の前(定義部とコール部で)に「&演算子」を置くと、その関数が変数を返そうとした場合、返されるものは変数の値ではなく変数へのリファレンスになる。

制御構造パート2

次回は、「制御構造」のページで解説しきれなかった、制御構造の残りの部分(「declare文」と「return文」、その他諸々)を解説します。

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