本篇文章基于PHP7.4.10
我们的测试脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?php
class Foo { public $a;
private $b;
public function __construct() { $this->a = 1; $this->b = 1; } }
$foo = new Foo;
printAllAttributeKeys($foo);
|
其中printAllAttributeKeys
是我们要编写的一个扩展函数,用来打印对象所有的属性名字。
因为PHP
属性是存在一个哈希表里面的,所以我们可以进行如下操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| static PHP_FUNCTION(printAllAttributeKeys) { zend_array *properties; zval *zobj; zend_ulong num; zend_string *key; zval *val;
ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 1, 1) Z_PARAM_OBJECT(zobj) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
#if PHP_VERSION_ID >= 70400 properties = zend_get_properties_for(zobj, ZEND_PROP_PURPOSE_VAR_EXPORT); #else if (Z_OBJ_HANDLER_P(zobj, get_properties)) { properties = Z_OBJPROP_P(zobj); } #endif
ZEND_HASH_FOREACH_KEY_VAL_IND(properties, num, key, val) { printf("%s\n", ZSTR_VAL(key)); } ZEND_HASH_FOREACH_END(); }
|
执行结果如下:
可以发现,只打印出了a
。实际上,对于b
这个属性,它在zend_string
里的存储内容为:
如果我们要打印出私有属性,我们可以作如下操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| const char *get_property_name(zend_string *property_name) { const char *class_name, *_property_name; size_t _property_name_len;
zend_unmangle_property_name_ex(property_name, &class_name, &_property_name, &_property_name_len);
return _property_name; }
static PHP_FUNCTION(printAllAttributeKeys) { zend_array *properties; zval *zobj; zend_ulong num; zend_string *key; zval *val;
ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 1, 1) Z_PARAM_OBJECT(zobj) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
#if PHP_VERSION_ID >= 70400 properties = zend_get_properties_for(zobj, ZEND_PROP_PURPOSE_VAR_EXPORT); #else if (Z_OBJ_HANDLER_P(zobj, get_properties)) { properties = Z_OBJPROP_P(zobj); } #endif
ZEND_HASH_FOREACH_KEY_VAL_IND(properties, num, key, val) { printf("%s\n", get_property_name(key)); } ZEND_HASH_FOREACH_END(); }
|
对属性key
这个zend_string
调用zend_unmangle_property_name_ex
即可获取到私有属性的名字。
执行结果如下: