PHPの配列は、キーのインデックスなどが配列側でしっかり管理されています。
$a = [];
$a[] = 1;
$a[10] = 2;
$a[] = 3;
var_dump($a); // [0=>1, 10=>2, 11=>3]
キーを空白にすると、自動的に次のインデックスを割り当ててくれます。
とても便利。
しかしこのインデックス、一度増えるとその後値を消しても戻りません。
$a = [0, 1];
unset($a[1]);
$a[] = 2;
var_dump($a); // [0=>0, 2=>2]
せっかく配列の最後の値を消したのに、使用した情報は残っていて次のキーは2になっています。
MySQLのauto_increment値と同様、一度上限が上がると下がらないということです。
全ての値を消したとしても同様です。
$a = [0, 1];
unset($a[1]);
unset($a[0]);
$a[] = 2;
var_dump($a); // [2=>2]
ところでこいつを見てくれ。
$a = [0, 1];
unset($a[1]);
unset($a[0]);
$b = $a;
$a[] = 2;
var_dump($a); // [0=>2] ←
$b=$a
と配列をコピーしたらインデックスの記憶が消え、また0から始まるようになりました。
なんでだよ。
さらにこっちも見てくれ。
$a = [0, 1];
unset($a[1]);
unset($a[0]);
$b = $a;
$a[] = 2;
$b[] = 3;
var_dump($a); // [0=>2]
var_dump($b); // [2=>3] ←
消えたと思っていたインデックスは、実はコピー先の$b
に移っていたようです。
なんでだよ。
ところでNormalize arrays' "auto-increment" value on copy on writeというRFCが提出されているのですが、これは配列のコピーの仕組みを変えようという内容です。
具体的には配列のコピーを、以下のコードと同じにします。
$array_copy = [];
foreach($array as $key => $value){
$array_copy[$key] => $value;
}
このRFCが適用されたらどうなるかというと、
$a = [0, 1];
unset($a[1]);
unset($a[0]);
$b = [];
foreach($a as $k=>$v){
$b[$k] = $v;
}
$a[] = 2;
$b[] = 3;
var_dump($a); // [2=>2]
var_dump($b); // [0=>3]
解決してなくない?