Help us understand the problem. What is going on with this article?

【PHP8.0】マイナススタートの配列インデックスが使えるようになる

PHP7.4
    $arr = [];
    $arr[-10] = 1;

    $arr[] = 1;

どうなるかというと[-10=>1, 0=>1]です。

これはマニュアルにも明記されています。

1.png

しかしこの動作は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+1n<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;

現在は全て以下のようになります。

~PHP7.4
array(3) {
  [-2]=>
  bool(true)
  [0]=>
  bool(true)
  [1]=>
  bool(true)
}

このRFCにより、以下の動作に変更になります。

PHP8.0~
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マイナスは使えないですし、あえて変更する必要があるのかは少し疑問です。

あと配列をコピーしたら何かおきそうで少し楽しみですね。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした