$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:キーは-0if($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もマイナスは使えないですし、あえて変更する必要があるのかは少し疑問です。
あと配列をコピーしたら何かおきそうで少し楽しみですね。