Home >Backend Development >PHP Tutorial >Detailed explanation of PHP custom function calling and execution process
The function being called requires some basic information, such as the name of the function, parameters and the definition of the function (that is, the specific execution content of the function). From the perspective of our developers, when a function is defined and we execute it Naturally, you know the name of this function, what parameters are passed when calling, and the operation content of the function. However, the Zend engine cannot "understand" the PHP source code like us. It needs to process the code before it can be executed. Let's start with the following two small examples:
<?php function foo(){ echo "I'm foo!"; } foo(); ?>
Next, let's take a look at the corresponding OPCODES:
Function name: (null) line# * OP FETCH EXT Return operands
----------------------------------------- ----------------------------------------
DO_FCALL 'foo'
attachment -------------------------------------------------- ------------------
4 0 > ECHO since ##The above is the opcodes with some peripheral information removed. You can see that the opcodes of the function part are independent during execution. This is particularly important for the execution of the function. The following part will introduce it in detail. Now, let's focus on the call to function foo. The OPCODE of calling foo is "DO_FCALL". When DO_FCALL performs a function call operation, ZE will search according to the function name in the function_table (as mentioned above, the function name here is processed by str_tolower, so PHP's function name is not case-sensitive) The definition of the function. If it does not exist, the
an internal function
or a user-defined function, call zend_execute_internal (zend_internal_function.handler) or directly call zend_execute to execute the zend_op_array contained in this function.
Execution of functions
Careful readers may notice that there is a "function name:" when the function is called in the above opcodes and in the function definition. In fact, the user
defines the function The execution of
内部函数的执行与用户函数不同。用户函数是php语句一条条“翻译”成op_line组成的一个op_array,而内部函数则是用C来实现的,因为执行环境也是C环境, 所以可以直接调用。如下面的例子:
<?php $foo = 'test'; print_r($foo); ?>
生成的opcodes中,内部函数和用户函数的处理都是由DO_FCALL来进行的。而在其具体实现的zend_do_fcall_common_helper_SPEC()中, 则对是否为内部函数进行了判断,如果是内部函数,则使用一个比较长的调用
((zend_internal_function *) EX(function_state).function)->handler(opline->extended_value, EX_T(opline->result.u.var).var.ptr, EX(function_state).function->common .return_reference?&EX_T(opline->result.u.var).var.ptr:NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
上面这种方式的内部函数是在zend_execute_internal函数没有定义的情况下。而在而在Zend/zend.c文件的zend_startup函数中,
zend_execute_internal = NULL;
此函数确实被赋值为NULL。于是我们在if (!zend_execute_internal)判断时会成立,所以我们是执行那段很长的调用。 那么,这段很长的调用到底是什么呢?以我们常用的 count函数为例。在4a863a0d9769be17e9a49a855df6b6bb>中, 我们知道内部函数所在的结构体中 有一个handler指针指向此函数需要调用的内部定义的C函数。 这些内部函数在模块初始化时就以扩展的函数的形式加载到EG(function_table)。其调用顺序:
php_module_startup --> php_register_extensions --> zend_register_internal_module
--> zend_register_module_ex --> zend_register_functions
zend_register_functions(NULL, module->functions, NULL, module->type TSRMLS_CC)
在standard扩展中。module的定义为:
zend_module_entry basic_functions_module = { STANDARD_MODULE_HEADER_EX, NULL, standard_deps, "standard", /* extension name */ basic_functions, /* function list */ ... //省略}
从上面的代码可以看出,module->functions是指向basic_functions。在basic_functions.c文件中查找basic_functions的定义。
The above is the detailed content of Detailed explanation of PHP custom function calling and execution process. For more information, please follow other related articles on the PHP Chinese website!