2012-02-28 40 views
3

我想实现这个类为PHP扩展不能更新类字段:PHP扩展:使用zend_hash_update

class MyClass { 
    protected $attrs = array(); 
    public function __construct($id = null) { 
    $this->attrs['id'] = $id; 
    $this->attrs['name'] = ''; 
    } 
    public function __get($key) { 
    if (array_key_exists($key, $this->attr)) 
     return $this->attrs[$key]; 
    } 
    public function __set($key, $value) { 
    if (array_key_exists($key, $this->attr)) 
     $this->attrs[$key] = $value; 
    } 
} 

我已经实现__constructor,$ ATTRS领域,__get方法。现在我无法看到__set。

还有就是我的C代码:

PHP_METHOD(MyClass, __set) {  
    char *key; 
    int key_len; 
    zval *value; 

    if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &key, &key_len, &value)) { 
    RETURN_NULL(); 
    } 

    zval *attrs, *obj; 
    obj = getThis(); 
    attrs = zend_read_property(Z_OBJCE_P(obj), obj, "attrs", strlen("attrs"), TRUE, TSRMLS_C); 

    if (Z_TYPE_P(attrs) == IS_ARRAY && zend_hash_exists(Z_ARRVAL_P(attrs), key, strlen(key) + 1)) { 
    zend_hash_update(Z_ARRVAL_P(attributes), key, strlen(key) + 1, &value, sizeof(zval*), NULL); 
    } 
    else {   
    zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 1, TSRMLS_C, "unknown field \"%s\"", key); 
    } 
} 

凡ATTRS - 在初始化函数声明为protected属性(我声明的属性为空,但是当我在构造函数中添加数据$ ATTRS - 属性更新是一个数组)

zend_declare_property_null(myclass_ce, "attrs", strlen("attrs"), ZEND_ACC_PROTECTED TSRMLS_CC); 

所以我的问题是:我需要如何更新我的attr字段在c? 我成功地扩展编译,我可以定义的属性,一定要读,但我不能将它们设置 - 因为设定值不变变为零,例如:

class MyClass2 extends MyClass { 
    public function __construct($id = null) { 
    parent::__construct($id); 
    $this->attrs["type"] = "clz"; 
    } 
} 

$c = new MyClass(); 
var_dump($c->type); // string(3) "clz" 
$c->type = "myclz"; // no error, my __set method handles this call, and I'm sure I'm getting correct value 
var_dump($c->type); // NULL 

我是新来的C开发,我真的需要帮助。

UPD 1.我试图改变__set体这样的:

zval *strval; 
MAKE_STD_ZVAL(strval); 
ZVAL_STRING(strval, Z_STRVAL_P(value), TRUE); 
if (Z_TYPE_P(attributes) == IS_ARRAY && zend_hash_exists(Z_ARRVAL_P(attributes), key, strlen(key) + 1)) { 
    zend_hash_update(HASH_OF(attributes), key, strlen(key) + 1, &strval, sizeof(zval*), NULL); 
} 

现在我可以设置字符串值。如果我需要切换每种类型的zval?

回答

3

这应该工作:

PHP_METHOD(MyClass, __set) {  
    char *key; 
    int key_len; 
    zval *value, *copied; 

    if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &key, &key_len, &value)) { 
    RETURN_NULL(); 
    } 

    zval *attrs, *obj; 
    obj = getThis(); 
    attrs = zend_read_property(Z_OBJCE_P(obj), obj, "attrs", strlen("attrs"), TRUE, TSRMLS_C); 

    MAKE_STD_ZVAL(copied); 
    *copied = *value; 
    zval_copy_ctor(copied); 

    if (Z_TYPE_P(attrs) == IS_ARRAY && zend_hash_exists(Z_ARRVAL_P(attrs), key, strlen(key) + 1)) { 
    zend_hash_update(Z_ARRVAL_P(attributes), key, strlen(key) + 1, &copied, sizeof(zval*), NULL); 
    } 
    else {   
    zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 1, TSRMLS_C, "unknown field \"%s\"", key); 
    } 
}