数组的解析也有两类,一类是解析到zval层面,另一类是解析到HashTable,其中"a"、"A"解析到的变量必须是zval,"h"、"H"解析到HashTable,这两类是等价的:
zval *arr; //必须是zval指针,不能是zval arr,因为参数保存在zend_execute_data上,arr为此空间上参数的地址
HashTable *ht;
if(zend_parse_parameters(ZEND_NUM_ARGS(), "ah", &arr, &ht) == FAILURE){
...
}
具体解析过程:
case 'A':
case 'a':
{
//解析到zval *
zval **p = va_arg(*va, zval **);
if (!zend_parse_arg_array(arg, p, check_null, c == 'A')) {
return "array";
}
}
break;
case 'H':
case 'h':
{
//解析到HashTable *
HashTable **p = va_arg(*va, HashTable **);
if (!zend_parse_arg_array_ht(arg, p, check_null, c == 'H')) {
return "array";
}
}
break;
"a!"、"A!"、"h!"、"H!"的用法与字符串一致,也不需要额外提供别的地址,如果传参为NULL,则对应解析到的zval、HashTable也为NULL。 > Note: > > 1、"a"与"A"当传参为数组时没有任何差别,它们的区别在于:如果传参为对象"A"将按照对象解析到zval,而"a"将报错 > > 2、"h"与"H"当传参为数组时同样没有差别,当传参为对象时,"H"将把对象的成员参数数组解析到目标变量,"h"将报错
如果参数是一个对象则可以通过"o"、"O"将其解析到目标变量,注意:只能解析为zval,无法解析为zend_object。
zval *obj;
if(zend_parse_parameters(ZEND_NUM_ARGS(), "o", &obj) == FAILURE){
...
}
"O"是要求解析指定类或其子类的对象,类似传参时显式的声明了参数类型的用法:function my_func(MyClass $obj){...},如果参数不是指定类的实例化对象则无法解析。
"o!"、"O!"与字符串用法相同。