OpenDogsエクステンションの次期バージョンではarray_merge()のオブジェクト版を実装する予定です。
返り値は与えられたオブジェクトのクラスによらず、stdClassのインスタンスです。
/* {{{ proto object od_object_merge(object obj1[, object obj2[, object ...]]) */ PHP_FUNCTION(od_object_merge) { #ifndef ZEND_ENGINE_2 HashTable *props = NULL; #endif zval ***params = NULL; int argc = ZEND_NUM_ARGS(); int i = 0; if (argc < 1) { WRONG_PARAM_COUNT; } params = (zval ***)ecalloc((size_t)argc, sizeof(zval **)); if (zend_get_parameters_array_ex(argc, params) == FAILURE) { efree(params); RETURN_NULL(); } if (object_init(return_value) != SUCCESS) { efree(params); RETURN_NULL(); } #ifndef ZEND_ENGINE_2 props = Z_OBJPROP_P(return_value); #endif while (i < argc) { zval **arg = params[i++]; if (Z_TYPE_PP(arg) == IS_OBJECT) { #ifdef ZEND_ENGINE_2 zend_merge_properties(return_value, Z_OBJPROP_PP(arg), 0 TSRMLS_CC); #else zend_hash_merge(props, Z_OBJPROP_PP(arg), (copy_ctor_func_t)zval_add_ref, NULL, sizeof(zval *), 1); #endif } else { php_error(E_WARNING, "Parameter %d must be an object", i); } } efree(params); } /* }}} od_object_merge */
が、エクステンションにするまでもなく、この程度で十分だと思い直したり。
<?php function my_object_merge() { $args = func_get_args(); if (!$args) { return null; } return (object)call_user_func_array('array_merge', array_map('get_object_vars', $args)); }
いずれも結果は以下のようになります。
<?php $a = &new stdClass(); $a->prop1 = 1.1; $a->prop2 = 2.1; $a->prop3 = 3.1; $b = &new stdClass(); $b->prop2 = 2.2; $b->prop3 = 3.2; $c = &new stdClass(); $c->prop3 = 3.3; var_dump(od_object_merge($a, $b, $c), my_object_merge($a, $b, $c));
object(stdClass)#4 (3) { ["prop1"]=> float(1.1) ["prop2"]=> float(2.2) ["prop3"]=> float(3.3) } object(stdClass)#5 (3) { ["prop1"]=> float(1.1) ["prop2"]=> float(2.2) ["prop3"]=> float(3.3) }