PHP の内部では、すべてがZVALと呼ばれるバリアントコンテナー内に格納されます。は ZVAL で表され、内部の各キーと各値は ZVAL などです。$data
$data
したがって、最初の割り当ての後、PHP から 3 つの ZVAL が作成されました。
/-------------------\ /-------------------\
| ZVAL #1 | /==>| ZVAL #2 |
| type: array | | | type: string |
| data: [ | | | data: "foo" |
| { | | \-------------------/
| key: =======/ /-------------------\
| val: ================================>| ZVAL #3 |
| } | | type: string |
| ] | | data: "bar" |
\-------------------/ \-------------------/
注: 配列項目の内部表現は、上記のものとは対応していません。不必要な詳細で答えに負担をかけたくありませんでした。ZVAL の表現も同じ理由で簡略化して示されています。PHP の内部構造について詳しく知りたい場合は、ソースおよび/またはこのをお読みください。
"foo"
およびが配列のキー/値のペアとして使用されているという事実は"bar"
、それらの ZVAL を見て判断することができないことがわかります。それらが配列によって参照されていることを知る必要があります。
割り当ての後、$data['baz'] = &$data
循環参照が発生します。ZVAL #1 内のどこかに、ZVAL #1 へのポインターがあります。
/-------------------\ /-------------------\
| ZVAL #1 | /==>| ZVAL #2 |
/=>| type: array | | | type: string |
| | data: [ | | | data: "foo" |
| | { | | \-------------------/
| | key: =======/ /-------------------\
| | val: ================================>| ZVAL #3 |
| | }, | | type: string |
| | { | | data: "bar" |
| | key: =========================\ \-------------------/
| | val: =========\ |
| | } | | | /-------------------\
| | ] | | \======>| ZVAL #4 |
| \-------------------/ | | type: string |
| | | data: "baz" |
\===========================/ \-------------------/
では、PHP はどのように解決するの$data['baz']['baz']
でしょうか。$data
が ZVAL#1 で表されていることを認識しており、配列構文でインデックスを作成しようとしていることがわかります。ZVAL を見て、それが配列であることを確認し、キー"baz"
を持つアイテムを見つけて、それを表す ZVAL を取得します。あなたは何を知っていますか?再びZVAL#1です。これで の解決は終了$data['baz']
です。
$data['baz']
次のステップで、配列としてインデックスを作成しようとしていることがわかります。それが$data['baz']
ZVAL#1 によって表されることを認識しているため、同じことが再び発生するなどです。
上記のプロセスでは、中間結果を保存する必要がないことに注意してください (最初のステップと 2 番目のステップは完全に独立しています)。つまり、配列アクセスを解決しようとするときに、PHP 仮想マシンがリソース制限に達することはありません。