对于PHPer来说,我们通常会将常用的??函数封装成一个函数进行复用,以提高开发效率。但是PHP如何找到对应的函数呢?今天,让我们一起来寻找答案吧~函数分类首先,我们来回顾一下PHP的函数分类。PHP函数包括用户自定义函数、内部函数、匿名函数等类型。对于用户自定义函数和内部函数,它们分别有自己的数据结构,但是为了适应这两类函数,Zend引擎定义了一个新的数据结构:zend_functionunion数据结构我们先来看看zend_functionunion,理解为什么typedefunion_zend_function{zend_uchartype;//函数类型用于标记是用户自定义函数还是内部函数struct{zend_uchartype;/*从未使用过*/char*function_name;//函数名zend_class_entry*scope;//函数所在的类作用域,用于标记所属类为成员方法zend_uintfn_flags;//标记作为类的成员方法时的访问类型,是public、protected还是privateunion_zend_function*prototype;//函数原型,zend_function,标记它所属的内部函数或用户自定义函数zend_uintnum_args;//函数的参数个数zend_uintrequired_num_args;//必须传递的参数个数zend_arg_info*arg_info;//参数信息指针zend_boolpass_rest_by_reference;无符号字符return_reference;//返回值}common;zend_op_arrayop_array;//用户自定义函数结构zend_internal_functioninternal_function;//内部函数结构}zend_function;struct_zend_op_array{/*公共元素(commonelements)*/zend_uchartype;字符*function_n我;zend_class_entry*范围;zend_uintfn_flags;union_zend_function*原型;zend_uintnum_args;zend_uintrequired_num_args;zend_arg_info*arg_info;zend_boolpass_rest_by_reference;无符号字符return_reference;/*公共元素结束*/zend_booldone_pass_two;....//其字符串}typedefstruct_zend_internal_function{/*公共元素(共有元素)*/zend_uchartype;字符*函数名;zend_class_entry*范围;zend_uintfn_flags;union_zend_function*原型;zend_uintnum_args;zend_uintrequired_num_args;zend_arg_info*arg_info;zend_boolpass_rest_by_reference;无符号字符return_reference;/*公共元素结束*/void(*handler)(INTERNAL_FUNCTION_PARAMETERS);结构_zend_module_entry*module;}zend_internal_function;从上面介绍的内容我们可以发现,无论是自定义函数还是内部函数,在底层存储的时候都会有公共字段type和common,所以他们以union的形式共享内存,这样可以节省内存空间并快速获取函数的基本信息,必要时可以完美的进行一些结构体之间的强制类型转换也就是说,zend_function可以和zend_op_array互换,zend_function可以和zend_internal_function互换。函数注册说完了自定义函数和内部函数的数据结构存储,再来看全局函数列表。全局函数列表可以理解为一个函数注册表,其内部实现是一个哈希表。自定义函数和内部函数编译完成后,函数名会被注册到全局函数列表中。即此时会判断全局函数列表中是否存在同名函数,那么用户自定义函数和内部函数存放在全局函数列表中有什么区别呢?自定义函数:我们写的php函数在编译阶段会经历词法分析->语法分析->生成中间代码opcode->执行中间代码的过程。执行中间代码时,函数名会注册到全局函数列表中作用:php启动时会加载所有扩展模块,在扩展模块中为每个函数创建一个zend_internal_function结构体,并将函数名注册到全局functionlist函数调用接下来,我们看一下如何调用一个函数,执行什么?当一个函数被调用时,它会首先根据函数名检查该函数是否存在于全局函数列表中。如果不存在,则直接报错信息“Calltoundefinedfunctionxxx()”;如果存在,则获取函数指针,对应的函数结构体中的type域决定了它的函数类型。如果函数类型是自定义函数,则调用zend_execute执行该函数的zend_op_array内容,如果函数类型是内部函数,则直接调用zend_internal_function的句柄指针指向的扩展模块的C函数总结在这里,你应该能找到我们一开始提出的问题的答案。其实就是通过将函数注册到全局函数列表中来实现的,然后当函数被调用时,会从全局函数列表中找到对应的函数执行;但是,对于用户自定义函数和内部函数,实现方式不同,当然这也意味着执行效率不同(当然PHP内部函数的执行效率更高,因为它没有运行时编译阶段,相当于直接执行C语言,所以会用PHP内部函数的尽量用内部函数)今天我们聊的就这些,欢迎大家手动点赞~
