14
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-01-16
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マイナスは使えないですし、あえて変更する必要があるのかは少し疑問です。

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

14
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?