PHP5での「foreach文」

「foreach文」でリファレンスを受け取る

反復文の一種である「foreach文」は、ループ中に配列なら要素(オプションで添え字も)を、オブジェクトならプロパティの値(オプションでプロパティ名も)が抽出され、その値が媒介用変数にコピーされていくというものでした。

PHP5では更に、ちょうど関数の“リファレンス渡し”のように、「&演算子」を使用してリファレンスを受け取る事が出来るようになりました。これにより、ループ中での値の更新がちょっと楽になります。以下のサンプルと結果をご覧下さい。

<pre>
<?php
    $arr = array("HODENASU1", "hode" => "HODENASU2", "HODENASU3");
    
    #ループ中に値を更新する
    foreach($arr as $key => $val){
        $arr[$key] = "-{$val}-";
    }
    
    foreach($arr as $key => $val){
        echo str_pad($key, 5), " : ", $val, "\n";
    }
    
    echo "\n";
    
    #ループ中に値を更新する(リファレンスを受け取る)
    foreach($arr as &$val){
        $val = "*{$val}*";
    }
    
    #「$val」をアンセットする(アンセットしないと問題が起こる場合もある)
    unset($val);
    
    foreach($arr as $key => $val){
        echo str_pad($key, 5), " : ", $val, "\n";
    }
    /*
    ※ループ前に「$val」をアンセットしていないと下記の様な結果になる
    「$arr[2]」に「$arr[0]」がセットされる→「*-HODENASU1-*」を出力
    「$arr[2]」に「$arr[1]」がセットされる→「*-HODENASU2-*」を出力
    「$arr[2]」に「$arr[2]」がセットされる→「*-HODENASU2-*」を出力
    */
    
    #変数ではないものからリファレンスを受け取ろうとすると・・・
    /*
    foreach(array("HODE", "NASU") as &$val){
        //
    }
    */
?>
</pre>
0     : -HODENASU1-
hode  : -HODENASU2-
1     : -HODENASU3-

0     : *-HODENASU1-*
hode  : *-HODENASU2-*
1     : *-HODENASU3-*
(Parse error:シンタックスエラー)

リファレンスを受け取った場合の方が更新が楽です。

変数ではないものからリファレンスを受け取る事は出来ません。間違った記述をすると「E_PARSE」エラーを発します。

オブジェクトプロパティの抽出

foreach文」では、オブジェクトのプロパティの抽出も出来ますが、PHP5では可視性等の関係で抽出できるものと出来ないものとがあります。以下のサンプルと結果をご覧下さい。

<pre>
<?php
    class HODE{
        public        $pub_var    = "public_property";
        protected     $pro_var    = "protected_property";
        private       $pri_var    = "private_property";
        static public $static_var = "static_property";
        public function __construct(){
            $i = 0;
            echo "****** begin HODE::__construct() ******\n";
            foreach($this as $name => $val){
                $i++;
                echo $name, " : ", $val, "\n";
            }
            echo "****** end HODE::__construct() ******\n";
            echo '$i : ', $i, "\n\n";
        }
    }
    
    class APETOPE extends HODE{
        public function __construct(){
            $i = 0;
            echo "****** begin APETOPE::__construct() ******\n";
            foreach($this as $name => $val){
                $i++;
                echo $name, " : ", $val, "\n";
            }
            echo "****** end APETOPE::__construct() ******\n";
            echo '$i : ', $i, "\n\n";
        }
    }
    
    new HODE;
    
    $obj = new APETOPE;
    
    $i = 0;
    echo "****** begin Outside of class ******\n";
    foreach($obj as $name => $val){
        $i++;
        echo $name, " : ", $val, "\n";
    }
    echo "****** end Outside of class ******\n";
    
    echo '$i : ', $i;
?>
</pre>
****** begin HODE::__construct() ******
pub_var : public_property
pro_var : protected_property
pri_var : private_property
****** end HODE::__construct() ******
$i : 3

****** begin APETOPE::__construct() ******
pub_var : public_property
pro_var : protected_property
****** end APETOPE::__construct() ******
$i : 2

****** begin Outside of class ******
pub_var : public_property
****** end Outside of class ******
$i : 1

アクセス可能なプロパティのみ出力されて、ループの回数はアクセス可能なプロパティ数分になっています。効率的に、アクセス可能なプロパティの数だけループされます。なお、クラスメンバであるスタティックプロパティは(オブジェクトプロパティではないので)出力されません。

作成日:2005年01月16日 最終更新日:2005年01月16日
【通常モード で表示】