ホームページ >バックエンド開発 >PHPチュートリアル >以前のバージョンと互換性のない PHP 5.6 の配列属性定義の分析

以前のバージョンと互換性のない PHP 5.6 の配列属性定義の分析

WBOY
WBOYオリジナル
2016-06-23 13:28:071153ブラウズ

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 以前のバージョンでは、クラスの配列メンバーを初期化するときに、一部のユニットに名前を付ける数値キーとしてシンボリック定数が使用されていましたが、これは配列のセマンティック定義と矛盾していました。

この状況は非常にまれであるため、影響は小さいですが、一度発生すると、それによって引き起こされるバグを検出するのは非常に困難です。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。