PHP resource type example sharing

小云云
Release: 2023-03-21 14:24:02
Original
1523 people have browsed it

In PHP, we often use resource type variables. For example: mysql connection, file handle, etc. These variables cannot be represented by scalars, so how do you connect resource variables in PHP to resources in C language in the Zend kernel?

1. The use of resource variables in PHP

  1. $fp = fopen("test.txt", "rw");  
      
    var_dump($fp);  
      
    fclose($fp);
    Copy after login

##Print results: resource(5) of type (stream)

Number 5: Indicates that the resource ID is 5. The specific meaning will be introduced later.

stream: resource type name.

2. Resource ID

The kernel stores the registered resource variables in a HashTable, and uses the key in the HashTable where the resource is located as the resource ID.

So, in fact, the resource variable in PHP actually stores an integer, and the corresponding resource in the HashTable is found through this ID.

    #define Z_RESVAL(zval)          (zval).value.lval  
    #define Z_RESVAL_P(zval)        Z_RESVAL(*zval)  
    #define Z_RESVAL_PP(zval)       Z_RESVAL(**zval)
    Copy after login
The above macro is the API used by ZE in the kernel to assign values ​​to resource variables. It can be seen that it is indeed an assignment to an integer variable.

3. Resource type name

In order to distinguish resource types, we need to define type names for the resources we define.

#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);//向内核中注册新的资源类型  
}
Copy after login


ZEND_MINIT_FUNCTION(jinyong) will be loaded in PHP as a SAPI (for example, Apache's mod_php5 extension) When reaching memory, all extended ZEND_MINIT_FUNCTION will be executed.

Among them, jinyong is the name of the current extension. For example, the name of the extension at this time is jinyong

For the convenience of understanding, we think of it as the extension registering a new resource type with the kernel during initialization.

4. Create resource variables

The resource type has been successfully registered, and a differentiated type name has been defined for the resource. Variables for this resource can now be used.

Implementing the fopen function in PHP:

    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返回资源变量  
    }
    Copy after login
Here, the function named my_fopen in PHP is defined. my_fopen(string $file_name, string $mode)

Implements the fclose function in PHP:

    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;  
    }
    Copy after login
defines the function named my_fclose in PHP function. my_fclose($resource)



##5. Compile and install the extension, restart php-fpm or mod_php5, etc.

6. Methods of using custom extensions in PHP

my_fwrite($fp, "aaTest");  
  
var_dump($fp);  
  
my_fclose($fp);  
  
var_dump($fp);
Copy after login
  1. Can open and close resources normally.

7. We often use database connection resources and file handle resources in PHP, but they usually do not require us to release them manually, and there will be no memory leak problems. How is this achieved?

my_resource_descriptor = zend_register_list_destructors_ex(NULL, NULL, MY_RES_NAME, module_number);//向内核中注册新的资源类型
Copy after login
  1. Go back to the original registered resource type and see the first parameter of zend_register_list_destructors_ex. This parameter is the pointer to the destructor.

Then, if you need to implement the automatic release function, you only need to define the destructor and pass the function pointer.

Look at another question:

$fp = fopen("test.txt", "rw");  
  
var_dump($fp);  
  
//fclose($fp); 此处不使用fclose释放资源  
  
unset($fp); //而是使用unset释放  
//unset没有问题,会正常释放$fp变量。但$fp对应真正的打开文件资源句柄资源将永远释放不了,直至mod_php5或php-fpm重启  
//可以看出,在注册资源类型时定义析构函数的必要性了
Copy after login
Define the destructor:

static void php_myres_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC){//析构函数被调用时,会接受一个当前资源变量的参数  
    FILE *fp = (FILE*)rsrc->ptr;  
    fclose(fp);  
}  
  
ZEND_MINIT_FUNCTION(jinyong)  
{  
    my_resource_descriptor = zend_register_list_destructors_ex(php_myres_dtor, NULL, MY_RES_NAME, module_number);  
}
Copy after login

    In PHP, the so-called resource variables actually store integer values, find the corresponding pointers in the kernel global resource variable list EG (regular_list), and perform corresponding operations.
  • The resource type is a special variable that holds a reference to an external resource. Resources are created and used through specialized functions.

Such as database connection, opening files, graphics canvas area, etc.

The resource type is actually just an integer, and the kernel can use this integer value to find the final required data in a place similar to a resource pool.

Example 1, example of file operation:


Code example:

<?php
$file=fopen(&#39;a.txt&#39;,&#39;r&#39;);//使用fopen函数打开一个文件获取句柄。  
fread($file,1024);//之后把该句柄传递给fread函数,即可对此文件进行后续操作。
Copy after login

Example 2, example of database operation:


Code example:

<?php
$result=mysql_query(&#39;select
 * from tbale&#39;);//mysql_query函数执行一条sql,若失败,返回false;成功,查询结果被缓存,并返回资源标识(类似:Resource
 id#42)即指向该资源的句柄。  
mysql_num_row($result);//使用该句柄可以操作缓存中的资源,从而返回查询出来的条数  
mysql_fetch_row($result);//使用该句柄可以操作缓存中的资源,从而返回查询结构
Copy after login

Description: List of functions that use and destroy resources.

You can use the is_resource() function to determine whether a variable is a resource, and the function get_resource_type() returns the type of the resource.

As for PHP resource variables, you don’t have to worry about issues like MYSQL connection not being released, because the destructor method is defined in the extension to help automatically release it.

Related recommendations:

PHP resource list, php resource_PHP tutorial

PHP resources

Summary of PHP resources, including: libraries, frameworks, templates, etc.

The above is the detailed content of PHP resource type example sharing. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template