ホームページ >バックエンド開発 >PHPチュートリアル >以前のバージョンと互換性のない PHP 5.6 の配列属性定義の分析
php5.6 公式ドキュメント (http://php.net/manual/zh/migration56.incompatibility.php) の非互換性ページでは、以前のバージョンとのいくつかの非互換性の状況について言及されており、クラス定義の定義時に言及されています。配列属性、元のテキストと例は次のとおりです。
PHP 5.6 より前のバージョンでは、クラスの配列型属性を定義するときに、明示的な配列キーと暗黙的な配列キーの両方が配列で使用されており、明示的な配列キーの場合は、キーと暗黙的なシーケンス キーが同じ場合、配列キーは上書きされます。例:
1 <?php 2 class C { 3 const ONE = 1; 4 public $array = [ 5 self::ONE => 'foo', 6 'bar', 7 'quux', 8 ]; 9 }10 11 var_dump((new C)->array);12 ?>
上記の例は PHP 5.5 での出力です:
1 array(2) {2 [0]=>3 string(3) "bar"4 [1]=>5 string(4) "quux"6 }
は PHP 5.6 での出力です:
array(3) { [1]=> string(3) "foo" [2]=> string(3) "bar" [3]=> string(4) "quux"}
上記の例は実際には非常に特殊なケースであり、そのためにはいくつかの前提条件があります。 :
1. 配列属性はクラスに対して定義する必要があり、クラス変数を定義するときに属性を初期化する必要があります。
2. 明示的な配列キーが最初であり、暗黙的な配列キーが最後である必要があります。暗黙的な配列キーは、表示されている配列キーの値をそれ自体と同じ位置に上書きします。暗黙的な配列キーが最初で、明示的な配列キーが後に定義されている場合、バージョンに関係なく、上書きが確実に行われます。 3. 明示的 配列キーは定数 (クラス定数を含む) である必要があります。リテラル定数の場合、上記の状況では、暗黙的な配列キーは明示的な配列キーをオーバーライドしません。以下の PHP の例 5.5 での出力:
1.1 非配列のようなメンバー定義:
1 $array = [2 ONE=>'foo',3 'bar',4 'quux'5 ];6 var_dump($array);
出力:
array(3) { [1] => string(3) "foo" [2] => string(3) "bar" [3] => string(4) "quux"}
1.2 非初期化代入:
1 define('ONE', 1);2 class C {3 public $array;4 }5 $c = new C;6 $c->array = [ONE=>'foo','bar','quux'];7 var_dump($c->array);
出力:
えー
array(3) { [1] => string(3) "foo" [2] => string(3) "bar" [3] => string(4) "quux"}
出力:
1 define('ONE', 1); 2 class C { 3 const ONE = 1; 4 public $array; 5 public function __construct() { 6 $this->array = array( 7 'bar', 8 ONE => 'foo', 9 'quux',10 );11 }12 }13 $c = new C;14 var_dump($c->array);
2. 暗黙的キーの明示的なキーオーバーライド:
array(3) { [0] => string(3) "bar" [1] => string(3) "foo" [2] => string(4) "quux"}
出力:
1 define('ONE', 1); 2 class C { 3 const ONE = 1; 4 public $array = array( 5 'bar', 6 'quux', 7 ONE => 'foo', 8 'guru' 9 );10 }11 $c = new C;12 var_dump((new C)->array);
3. 明示的なキー名としてのリテラル定数:
出力:
rree
array(3) { [0] => string(3) "bar" [1] => string(3) "foo" [2] => string(4) "guru"}
出力:
1 class C { 2 public $array = array( 3 'bar', 4 'quux', 5 1 => 'foo', 6 'guru' 7 ); 8 } 9 $c = new C;10 var_dump((new C)->array);
実際、本質的に、これは深く隠された小さなバグです。
配列の定義で、一部のユニットが数値キー名を指定している場合、後続の暗黙的キー名は以前の最大の数値 (暗黙的または明示的を含む) キー名を継続し、暗黙的キー名のオーバーライドは発生しません。明示的な数値キー名。明示的なキー名がリテラル定数であるかシンボリック定数であるか。
公式マニュアルの配列セクションを参照してください: http://php.net/manual/zh/ language.types.array.php:
array(3) { [0] => string(3) "bar" [1] => string(3) "foo" [2] => string(4) "guru"}
上記のルーチンは出力します:
1 class C {2 public $array = array(3 1 => 'foo',4 'bar',5 'quux',6 );7 }8 $c = new C;9 var_dump((new C)->array);
ただ、 5.6 以前のバージョンでは、クラスの配列メンバーを初期化するときに、一部のユニットに名前を付ける数値キーとしてシンボリック定数が使用されていましたが、これは配列のセマンティック定義と矛盾していました。
この状況は非常にまれであるため、影響は小さいですが、一度発生すると、それによって引き起こされるバグを検出するのは非常に困難です。