首頁  >  文章  >  後端開發  >  php:資源(resource)資料類型實例詳解

php:資源(resource)資料類型實例詳解

怪我咯
怪我咯原創
2018-05-16 16:08:0718284瀏覽

什麼是資源資料型別?

資源資料型態是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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn