mirror of
https://github.com/deuill/go-php.git
synced 2024-09-21 00:40:45 +00:00
Add struct-to-object value bindings
This commit is contained in:
parent
7ed2c81ec6
commit
6a3fd786ea
17
php_test.go
17
php_test.go
@ -120,12 +120,29 @@ var bindTests = []struct {
|
||||
value interface{} // Value to bind
|
||||
expected string // Serialized form of value
|
||||
}{
|
||||
// Integer to integer.
|
||||
{42, "i:42;"},
|
||||
// Float to double.
|
||||
{3.14159, "d:3.1415899999999999;"},
|
||||
// Boolean to boolean.
|
||||
{true, "b:1;"},
|
||||
// String to string.
|
||||
{"Such bind", `s:9:"Such bind";`},
|
||||
// Simple slice of strings to indexed array.
|
||||
{[]string{"this", "that"}, `a:2:{i:0;s:4:"this";i:1;s:4:"that";}`},
|
||||
// Nested slice of integers to indexed array.
|
||||
{[][]int{[]int{1, 2}, []int{3}}, `a:2:{i:0;a:2:{i:0;i:1;i:1;i:2;}i:1;a:1:{i:0;i:3;}}`},
|
||||
// Struct to object, with nested struct.
|
||||
{struct {
|
||||
I int
|
||||
C string
|
||||
F struct {
|
||||
G bool
|
||||
}
|
||||
h bool
|
||||
}{3, "test", struct {
|
||||
G bool
|
||||
}{false}, true}, `O:8:"stdClass":3:{s:1:"I";i:3;s:1:"C";s:4:"test";s:1:"F";O:8:"stdClass":1:{s:1:"G";b:0;}}`},
|
||||
}
|
||||
|
||||
func TestContextBind(t *testing.T) {
|
||||
|
@ -62,6 +62,19 @@ void value_array_set_key(void *arr, const char *key, void *val) {
|
||||
add_assoc_zval((zval *) arr, key, (zval *) val);
|
||||
}
|
||||
|
||||
void *value_create_object() {
|
||||
zval *v;
|
||||
|
||||
MAKE_STD_ZVAL(v);
|
||||
object_init(v);
|
||||
|
||||
return (void *) v;
|
||||
}
|
||||
|
||||
void value_object_add_property(void *obj, const char *key, void *val) {
|
||||
add_property_zval((zval *) obj, key, (zval *) val);
|
||||
}
|
||||
|
||||
void value_destroy(void *zvalptr) {
|
||||
zval_dtor((zval *) zvalptr);
|
||||
}
|
@ -53,9 +53,10 @@ func (v *Value) Destroy() {
|
||||
// map[int|string] -> associative array
|
||||
// struct -> object
|
||||
//
|
||||
// Bindings for functions and method receivers to PHP functions and classes are
|
||||
// only available in the engine scope, and must be predeclared before context
|
||||
// execution.
|
||||
// It is only possible to bind maps with integer or string keys. Only exported
|
||||
// struct fields are passed to the PHP context. Bindings for functions and method
|
||||
// receivers to PHP functions and classes are only available in the engine scope,
|
||||
// and must be predeclared before context execution.
|
||||
func New(val interface{}) (*Value, error) {
|
||||
var ptr unsafe.Pointer
|
||||
|
||||
@ -74,9 +75,9 @@ func New(val interface{}) (*Value, error) {
|
||||
// Bind string to PHP string type.
|
||||
case reflect.String:
|
||||
str := C.CString(v.String())
|
||||
defer C.free(unsafe.Pointer(str))
|
||||
|
||||
ptr = C.value_create_string(str)
|
||||
C.free(unsafe.Pointer(str))
|
||||
// Bind slice to PHP indexed array type.
|
||||
case reflect.Slice:
|
||||
ptr = C.value_create_array(C.uint(v.Len()))
|
||||
@ -84,6 +85,7 @@ func New(val interface{}) (*Value, error) {
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
vs, err := New(v.Index(i).Interface())
|
||||
if err != nil {
|
||||
C.value_destroy(ptr)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -99,6 +101,7 @@ func New(val interface{}) (*Value, error) {
|
||||
for _, key := range v.MapKeys() {
|
||||
kv, err := New(v.MapIndex(key).Interface())
|
||||
if err != nil {
|
||||
C.value_destroy(ptr)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -114,6 +117,28 @@ func New(val interface{}) (*Value, error) {
|
||||
} else {
|
||||
return nil, errInvalidType
|
||||
}
|
||||
// Bind struct to PHP object (stdClass) type.
|
||||
case reflect.Struct:
|
||||
vt := v.Type()
|
||||
ptr = C.value_create_object()
|
||||
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
// Skip unexported fields.
|
||||
if vt.Field(i).PkgPath != "" {
|
||||
continue
|
||||
}
|
||||
|
||||
fv, err := New(v.Field(i).Interface())
|
||||
if err != nil {
|
||||
C.value_destroy(ptr)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
str := C.CString(vt.Field(i).Name)
|
||||
|
||||
C.value_object_add_property(ptr, str, fv.Ptr())
|
||||
C.free(unsafe.Pointer(str))
|
||||
}
|
||||
default:
|
||||
return nil, errInvalidType
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ void *value_create_string(char *value);
|
||||
void *value_create_array(unsigned int size);
|
||||
void value_array_set_index(void *arr, unsigned long idx, void *val);
|
||||
void value_array_set_key(void *arr, const char *key, void *val);
|
||||
void *value_create_object();
|
||||
void value_object_add_property(void *obj, const char *key, void *val);
|
||||
void value_destroy(void *zvalptr);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user