$arr = [];
$arr[-10] = 1;
$arr[] = 1;
どうなるかというと[-10=>1, 0=>1]
です。
これはマニュアルにも明記されています。
しかしこの動作はPHP8.0で変更になります。
Arrays starting with a negative indexというRFCにおいて変更が決定しました。
Arrays starting with a negative index
Introduction
array_fillのドキュメントには、『start_index が負の場合は、 返される配列の最初のインデックスが start_index となり、それ以降のインデックスはゼロから始まります』とあります。
明示的に負のキーを使用し、その後キーを省略した場合は常にこのような動作になります。
Proposal
現在の動作は、最後の数値キーがnであった場合、次の暗黙キーはn>=0
であればn+1
、n<0
であれば0
ということになります。
このRFCでは、nの符号に関係なく常にn+1
とすることによって、この動作を一貫させることを目指しています。
配列のドキュメントにもわざわざ注釈として書かれているように、これは例外的な動作であり、学習コストとなります。
このプロポーザルはPHP8.0を対象としています。
この変更により問題が発生する可能性がある場合、移行を容易にするために非推奨の通知を出すことも提案します。
以下のコードは全て同じ結果になります。
$a = array_fill(-2, 3, true);
$b = [-2 => true, true, true];
$c = ["string" => true, -2 => true, true, true];
unset($c["string"]);
$d[-2] = true;
$d[] = true;
$d[] = true;
現在は全て以下のようになります。
array(3) {
[-2]=>
bool(true)
[0]=>
bool(true)
[1]=>
bool(true)
}
このRFCにより、以下の動作に変更になります。
array(3) {
[-2]=>
bool(true)
[-1]=>
bool(true)
[0]=>
bool(true)
}
非推奨を出力する投票が受理された場合、移行フェーズ中は以下のE_DEPRECATEDを発生させます。
Deprecated: In the next major version of PHP the implicit keys of this array will start from -1 instead of 0 in ...
Backward Incompatible Changes
配列を負のインデックスから開始し、その後暗黙のキーを使い、そして明示的なキーで配列要素にアクセスした際に影響が発生します。
$a[-2] = true; // 現行:キーは-2 / RFC:キーは-2
$a[] = true; // 現行:キーは0 / RFC:キーは-1
$a[] = true; // 現行:キーは1 / RFC:キーは-0
if ($a[1] === true) {
echo 'Accessing key 1 explicitly';
}
PHP8.0以降、'Accessing key 1 explicitly'が出力されなくなります。
Proposed PHP Version(s)
PHP8.0。
Unaffected PHP Functionality
明示的なキー、文字列のキーには影響しません。
また、-1以上の数値インデックスを持つ配列も影響を受けません。
最初から暗黙のキーを使う配列のインデックスは0から始まります。
キーを使用しないforeachも影響を受けません。
投票
このRFCは賛成17反対2で可決されました。
E_DEPRECATEDを出す提案は賛成8反対14で却下されました。
すなわち、PHP8.0で前触れなく突然動作が変更になります。
感想
PHP4.2から長い時を経て、元の鞘に戻ることになりました。
さすがに当時のことは知らないので、どうして変更されたのかは全くわかりません。
しかし、この仕様に依存する実装をしている人なんていないでしょう。
すなわち実質的な影響はほぼゼロです。
そもそもネガティブスタートの配列って何に使うんだろうか?
ただ、MySQLのAUTO_INCREMENTもマイナスは使えないですし、あえて変更する必要があるのかは少し疑問です。
あと配列をコピーしたら何かおきそうで少し楽しみですね。