重写对象处理程序
如果你还记得,每个对象都有一个对象处理程序表。我们在上一章嵌入 C 数据时已经开始使用它。
有许多不同的处理程序,所有这些处理程序都可以重载,以改变对象的行为。例如:
-
ArrayObject 重载 read/write/has/unset_dimension 处理程序,使对象表现为数组。
-
ext/simplexml 允许通过属性和维度处理程序遍历 XML 树。
-
ext/ffi 通过 get_method 处理程序等调用本地函数。
我们将覆盖 get_debug_info 处理程序,使 var_dump() 打印 C 因子字段的值。该方法接收 "对象" 参数,并返回一个包含要显示的 zvals 属性的 HashTable。默认实现返回一个真正的 PHP 属性表,但我们没有任何 PHP 属性。因此,我们使用神奇的名称 {factor}
来构建一个新的属性并添加 C 因子的值。我们还指定这不是真正的属性表,而是一个临时表,打印后应释放。
static HashTable* scaler_get_debug_info(zval *object, int *is_temp)
{
scaler_t *scaler = OBJ_SCALER(object);
HashTable *ret = zend_new_array(1);
zval tmp;
ZVAL_LONG(&tmp, scaler->factor);
zend_hash_str_add(ret, "{factor}", sizeof("{factor}")-1, &tmp);
*is_temp = 1;
return ret;
}
当然,我们必须自己覆盖 Scaler 类中 get_debug_info 处理程序的默认值。
memcpy(&scaler_object_handlers, &std_object_handlers,
sizeof(zend_object_handlers));
scaler_object_handlers.offset = XtOffsetOf(scaler_t, std);
scaler_object_handlers.get_debug_info = scaler_get_debug_info;
zend_declare_class_constant_long(scaler_class_entry,
"DEFAULT_FACTOR", sizeof("DEFAULT_FACTOR")-1, DEFAULT_SCALE_FACTOR);
工作没有问题:
$ php -r '$o = new Scaler(4); $x = 5; $o->scale($x); var_dump($x,$o);'
int(20)
object(Scaler)#1 (1) {
["{factor}"]=>
int(4)
}