As far as I know, this is not what ZEND_BEGIN_ARG_INFO_EX
is for.
ZEND_BEGIN_ARG_INFO_EX
is a PHP 5 addition is used for producing cleaner code, enabling type hinting, pass-by-reference and reflection. Consider the following arginfo declarations for your actual function that just returns 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()
It has the following effect:
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
Additionally, it provides reflection capabilities to your function:
$ref = new ReflectionFunction('sample_with_types');
var_dump($ref->getParameters());
...giving output similar to:
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"
}
}
If you omit the arginfo, ReflectionFunction::getParameters()
returns an empty array instead.
The required_num_args
macro parameter is used specifically for reflection, and denotes how many parameters will be marked required when reflecting the function.
If you need to make the arguments required and not just mark them as required when using reflection, you still have to use zend_parse_parameters
, which in most cases, you will still need to get the actual values of the arguments:
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;
}
Note how I used "looo"
(generic object types) and not "lOO!O!"
(specific object types with null specifiers) in the above. The type hinting already has been specified with arginfo, so there's no need to do it twice.
So, without arginfo:
- You'd have to use a handful of
zend_fetch_class
calls and class entries to type hint your object arguments. - It wouldn't enable reflection.
- You wouldn't be able to declare arguments passed by reference.
- It would obviously produce less clean code.
For obvious reasons, you'll want to make sure both your arginfo declaration and your zend_parse_parameters
call matches.