オブジェクトのプロパティをマージ

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)
}