据我所知,这不是ZEND_BEGIN_ARG_INFO_EX
目的。
ZEND_BEGIN_ARG_INFO_EX
是 PHP 5 的新增功能,用于生成更简洁的代码、启用类型提示、引用传递和反射。考虑以下 arginfo 声明,用于只返回 true 的实际函数:
ZEND_BEGIN_ARG_INFO_EX(arginfo_test, 0, 0, 3)
ZEND_ARG_INFO(0, firstArg)
ZEND_ARG_OBJ_INFO(0, objNonNull, stdClass, 0)
ZEND_ARG_OBJ_INFO(0, obj, stdClass, 1)
ZEND_ARG_OBJ_INFO(1, objByRef, stdClass, 1)
ZEND_END_ARG_INFO()
它具有以下效果:
sample_with_types(); // ok
sample_with_types(1, null); // error: arg #2 should be stdClass
sample_with_types(1, new stdClass, null); // ok
sample_with_types(1, new stdClass, 1); // error: arg #3 should be stdClass
sample_with_types(1, new stdClass, null, 2); // error: arg #4 must be reference
此外,它还为您的函数提供反射功能:
$ref = new ReflectionFunction('sample_with_types');
var_dump($ref->getParameters());
...给出类似于以下内容的输出:
array(4) {
[0]=>
&object(ReflectionParameter)#2 (1) {
["name"]=>
string(8) "firstArg"
}
[1]=>
&object(ReflectionParameter)#3 (1) {
["name"]=>
string(10) "objNonNull"
}
[2]=>
&object(ReflectionParameter)#4 (1) {
["name"]=>
string(3) "obj"
}
[3]=>
&object(ReflectionParameter)#5 (1) {
["name"]=>
string(8) "objByRef"
}
}
如果省略 arginfo,则ReflectionFunction::getParameters()
返回一个空数组。
宏参数专门用于反射,required_num_args
表示反射函数时需要多少个参数。
如果您需要使参数成为必需,而不仅仅是在使用反射时将它们标记为必需,您仍然必须使用zend_parse_parameters
,在大多数情况下,您仍然需要获取参数的实际值:
PHP_FUNCTION(sample_with_types)
{
long arg1;
zval *arg2 = NULL, *arg3 = NULL, *arg4 = NULL;
zend_class_entry ce2, ce3, ce4;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "looo", &arg1,
&arg2, &ce2, &arg3, &ce3, &arg4, &ce4) == FAILURE)
{
return;
}
RETURN_TRUE;
}
请注意我在上面如何使用"looo"
(通用对象类型)而不是"lOO!O!"
(具有空说明符的特定对象类型)。类型提示已经用 arginfo 指定了,所以不需要重复两次。
所以,没有 arginfo:
- 您必须使用少量
zend_fetch_class
调用和类条目来键入提示您的对象参数。
- 它不会启用反射。
- 您将无法声明通过引用传递的参数。
- 它显然会产生不太干净的代码。
出于显而易见的原因,您需要确保 arginfo 声明和zend_parse_parameters
调用匹配。