什麼是資源資料型別?
資源資料型態是PHP4引進的。資源是一種特殊的變數類型,保存了到外部資源的一個參考:如開啟檔案、資料庫連線、圖形畫布區域等。
資源是透過專門的函數來建立和使用的。
資源變數在PHP中的使用
$fp = fopen("test.txt", "rw"); var_dump($fp); fclose($fp);
列印結果:resource(5) of type (stream)
數字5:表示資源ID為5,具體意義後面介紹。
stream:資源型別名稱。
資源ID
核心中將註冊的資源變數儲存在一個HashTable中,並將資源所在HashTable中的key當作資源ID。
所以,實際上PHP中的資源變數實際儲存的是一個整數,透過這個ID找到HashTable中對應的資源。
#define Z_RESVAL(zval) (zval).value.lval #define Z_RESVAL_P(zval) Z_RESVAL(*zval) #define Z_RESVAL_PP(zval) Z_RESVAL(**zval)
上面的宏,是核心中ZE為資源變數賦值的API,看出確實是對整數變數的賦值。
資源類型名稱
為了區分資源類型,需要為我們定義的資源定義類型名稱。
#define MY_RES_NAME "my_resource" //资源类型名称,PHP通过var_dump打印资源变量时会看到这个名称 static int my_resource_descriptor; ZEND_MINIT_FUNCTION(jinyong) { my_resource_descriptor = zend_register_list_destructors_ex(NULL, NULL, MY_RES_NAME, module_number);//向内核中注册新的资源类型 }
ZEND_MINIT_FUNCTION(jinyong)會在PHP作為SAPI(例如,Apache的mod_php5擴充)被載入到記憶體時,會執行所有擴充的ZEND_MINIT_FUNCTION。
其中jinyong,是目前擴充的名字。例如此時擴充的名字就是jinyong
這裡為了方便理解,我們就把它認為是擴充在初始化時,會向核心註冊新的資源型別。
建立資源變數
資源類型已經註冊成功,也為資源定義了區分的類型名稱。現在可以使用這種資源的變數了。
實作PHP中的fopen函數:
PHP_FUNCTION(my_fopen) { zval *res; char *filename, *mode; int filename_strlen, mode_strlen; FILE *fp; if(zend_parse_parameters(ZEND_NUM_ARGS TSRMLS_CC, "s|s", &filename, &filename_strlen, &mode, &mode_strlen) == FAILURE){ RETURN_FALSE; } //此处省略了对参数的有效性验证 fp = fopen(filename, mode); ZEND_REGISTER_RESOURCE(res, fp, my_resource_descriptor);//向全局变量&EG(regular_list)中注册资源变量,并将对应HashTable的ID赋值给res RETURN_RESOURCE(res);//向PHP返回资源变量 }
這裡,定義了PHP中名稱為my_fopen的函數。 my_fopen(string $file_name, string $mode)
實作PHP中的fclose函數:
PHP_FUNCTION(my_fclose) { zval *res; FILE *fp; if(zend_parse_parameters(ZEND_NUM_ARGS TSRMS_CC, "r", &res) == FAILURE){ RETURN_FALSE; } if(Z_TYPE_P(res) == IS_RESOURCE){//判断变量类型是否是资源类型 zend_hash_index_del(&EG(regular_list), Z_RESVAL_P(res));//EG就类似于PHP中的$_GLOBALS。在全局资源变量regular_list中删除对应ID的资源 }else{ php_error_docref(NULL TSRMLS_CC, E_WARNING, "参数必须是资源类型变量"); RETURN_FALSE; } RETURN_TRUE; }
定義了PHP中名稱為my_fclose的函數。 my_fclose($resource)
PHP中使用自訂擴充功能中的方法
my_fwrite($fp, "aaTest"); var_dump($fp); my_fclose($fp); var_dump($fp);
可以正常,開啟和關閉資源。
釋放資源
由於 PHP4 Zend 引擎引進了資源計數系統,可以自動偵測到一個資源不再被引用了(和 Java 一樣)。這種情況下此資源所使用的所有外部資源都會被垃圾回收系統釋放。因此,很少需要用某些 free-result 函數來手動釋放記憶體。
注意: 持久性資料庫連線比較特殊,它們不會被垃圾回收系統破壞。
下一節,我們說明兩種特殊資料類型中的「空值(null)」。
以上是php:資源(resource)資料類型實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!