Home > Article > Backend Development > PHP source code — is_array function source code analysis
is_array in php
is_array in php, its signature is is_array (mixed $var): bool
The source code of the implementation
can be found in \ext\standard\type.c
PHP_FUNCTION(is_array)
The location is approximately line 273.
In PHP, this series of functions consists of many functions. In addition to itself, there are also is_bool, is_countable, is_callback, is_int, is_object, is_string, etc.
Between them , most of the source code is similar to is_array:
PHP_FUNCTION(is_array) { php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_ARRAY); }
Its definition is very concise, directly calling php_is_type
, the function of the macro INTERNAL_FUNCTION_PARAM_PASSTHRU
is , pass the parameters when calling is_array to php_is_type as they are. It is defined as follows:
#define INTERNAL_FUNCTION_PARAM_PASSTHRU execute_data, return_value
The function php_is_type is defined as follows:
static inline void php_is_type(INTERNAL_FUNCTION_PARAMETERS, int type) { zval *arg; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ZVAL(arg) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); if (Z_TYPE_P(arg) == type) { if (type == IS_RESOURCE) { const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg)); if (!type_name) { RETURN_FALSE; } } RETURN_TRUE; } else { RETURN_FALSE; } }
The first few lines are the parameter parsing part
ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ZVAL(arg) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
Then it passes Z_TYPE_P(arg)
Get the type of the variable, and then let the result be equal to IS_ARRAY
. If true, it means the variable is an array, otherwise it is not. The role of Z_TYPE_P is obvious, it is to get the type of the variable. After expansion of this macro, it is as follows:
static zend_always_inline zend_uchar zval_get_type(const zval* pz) { return pz->u1.v.type; }
where pz is the zval pointer, and zval is the often mentioned _zval_struct
:
struct _zval_struct { zend_value value;/* 值 */ union { struct { ZEND_ENDIAN_LOHI_3( zend_uchar type,/* 类型 */ zend_uchar type_flags, union { uint16_t call_info; /* call info for EX(This) */ uint16_t extra; /* not further specified */ } u) } v; uint32_t type_info; } u1; union { uint32_t next; /* hash 碰撞时用到的链表 */ uint32_t cache_slot; /* cache slot (for RECV_INIT) */ uint32_t opline_num; /* opline number (for FAST_CALL) */ uint32_t lineno; /* 行号 (ast 节点中) */ uint32_t num_args; /* 参数数量 for EX(This) */ uint32_t fe_pos; /* foreach 时的所在位置 */ uint32_t fe_iter_idx; /* foreach iterator index */ uint32_t access_flags; /* 类时的访问权限标志位 */ uint32_t property_guard; /* single property guard */ uint32_t constant_flags; /* constant flags */ uint32_t extra; /* 保留字段 */ } u2; };
I won’t give an in-depth introduction.
Continue to see php_is_type
When judging the type,
There is a strange place: if (type == IS_RESOURCE) {
Why do we need to determine whether it is a resource type?
Extended resource type
Extend here. If php_is_type is used to determine the resource type
it will be called here const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg));
There is a call to zend_rsrc_list_get_rsrc_type, which is implemented as follows:
const char *zend_rsrc_list_get_rsrc_type(zend_resource *res) { zend_rsrc_list_dtors_entry *lde; lde = zend_hash_index_find_ptr(&list_destructors, res->type); if (lde) { return lde->type_name; } else { return NULL; } }
There is a static variable called list_destructors
, its The function is as follows
list_destructors is a global static HashTable. When the resource type is registered, a zval structure variable zv is stored in the arData of list_destructors, but the value.ptr of zv points to zend_rsrc_list_dtors_entry *lde. The resource release function pointer contained in lde, the release function pointer of the persistent resource, the resource type name, the index basis of the resource in the hashtable (resource_id), etc. --From "Analysis of the third-party extension principle of using resource wrapping in PHP7"
That is to say, when a resource type R1 is created, a resource type R1 will be stored in list_destructors
Part zend_rsrc_list_dtors_entry
, which contains some information about the resource R1
The zend_hash_index_find_ptr
is to find the zend_rsrc_list_dtors_entry
corresponding to the resource, and then take the lde->type_name
If the type member exists, it means that it is a resource type.
Summary
is_*
series of functions used in PHP to determine the type, most of which use u1 in the underlying zval of the variable .v.type
To determine the type value, if it is a resource type, you need to query whether the corresponding resource type exists through list_destructors. If it exists, it means that the resource handle can be used normally.
For more PHP related technical articles, please visit the PHP Tutorial column to learn!
The above is the detailed content of PHP source code — is_array function source code analysis. For more information, please follow other related articles on the PHP Chinese website!