PHP は、弱く型付けされた動的言語スクリプトです。変数を宣言するとき、変数が保持するデータ型を指定する必要はありません。例:
<?php $var = 1; $var = "variable"; $var = 1.00; $var = array(); $var = new Object();
動的変数は実行時に変更でき、使用前に変数の型を宣言する必要はありません。
質問 1. Zend エンジンはこの弱い型を C でどのように実装しますか?
実際、PHP で宣言された変数は、zval 構造体を使用して ZE に格納されます。
まず、Zend/zend.h を開いて zval の定義を確認します:
typedef struct _zval_struct zval; struct _zval_struct { /* Variable information */ zvalue_value value; /* value */ zend_uint refcount__gc; zend_uchar type; /* active type */ zend_uchar is_ref__gc; }; typedef union _zvalue_value { long lval; /* long value */ double dval; /* double value */ struct { char *val; int len; } str; HashTable *ht; /* hash table value */ zend_object_value obj; } zvalue_value;
Zend/zend_types.h:
typedef unsigned char zend_bool; typedef unsigned char zend_uchar; typedef unsigned int zend_uint; typedef unsigned long zend_ulong; typedef unsigned short zend_ushort;
上記のコードから、_zvalue_value が実際にデータを保存するための重要な部分であることがわかります。 Union による弱い型指定の変数宣言
質問 2. Zend エンジンはどのようにして PHP で複数のデータ型を識別し、保存しますか?
_zval_struct.type は変数の実際の型を格納し、その型に基づいて zvalue_value の値を取得する方法を選択できます。
type value list (Zend/zend.h):
#define IS_NULL 0 #define IS_LONG 1 #define IS_DOUBLE 2 #define IS_BOOL 3 #define IS_ARRAY 4 #define IS_OBJECT 5 #define IS_STRING 6 #define IS_RESOURCE 7 #define IS_CONSTANT 8 #define IS_CONSTANT_ARRAY 9
簡単な例を見てみましょう:
<?php $a = 1; //此时zval.type = IS_LONG,那么zval.value就去取lval. $a = array(); //此时zval.type = IS_ARRAY,那么zval.value就去取ht.
これらの中で最も複雑で、サードパーティの拡張機能の開発でよく使用されるのは、「リソース」です。 「型」
PHPでは、PHPの組み込み変数の型に属さない変数はリソースとして扱われ、保存されます。
例: データベース ハンドル、オープン ファイル ハンドル、オープン ソケット ハンドル。
リソースタイプは、この時点では整数インジケーターである lval を使用します。その後、PHP は、このインジケーターに基づいて、PHP で構築されたリソースリスト内の対応するリソースをクエリします。
PHPが弱い型を実装しているのはZEの処理方式だからこそであり、ZEにとっては常に同じ型のzvalと対峙することになります。