今回は配列カーソルの話です。
PHP の配列には、『現在配列のここを見てますよ』というのを覚えておくカーソルというものがあります。
例えば次のような配列があるとします。
$fruit = array('a' => 'apple', 'b' => 'banana', 'c' => 'cranberry');
each 関数は 配列のキーと値のペアを返しますが 使用するたびに次の要素に移動します。
$a = each($fruit); // 'a', 'apple' が代入される $b = each($fruit); // 'b', 'banana' が代入される $c = each($fruit); // 'c', 'cranberry' が代入される $d = each($fruit); // FALSE が代入される
こんなことができるのは 配列が内部的に現在の位置を覚えているためです。
次の while ができるのも同じ理由です。
while (list($key, $val) = each($fruit)) { echo "$key => $val\n"; }
カーソルを初期化するための reset という関数があります。
reset($fruit); while (list($key, $val) = each($fruit)) { echo "$key => $val\n"; }
他で参照されている可能性がある場合 上のようにループ処理の前では カーソルを初期化します。
気をつけなくてはならないのは、 カーソルは「配列を別の変数に代入すると初期化される」という仕様です。 「配列に変数を」ではなく「変数に配列を」なのがわかりにくいところです。
次のコードは無限ループになってしまいます。
$fruit = array('a' => 'apple', 'b' => 'banana', 'c' => 'cranberry'); while (list($key, $val) = each($fruit)) { echo "$key => $val\n"; $food = $fruit; // この処理でカーソルが初期化される }
上の処理は次の処理と同じです。
$fruit = array('a' => 'apple', 'b' => 'banana', 'c' => 'cranberry'); $food = $fruit; while (list($key, $val) = each($fruit)) { echo "$key => $val\n"; reset($fruit); // この処理でカーソルが初期化される }