dcarbone/php-object-merge
PHP对象属性合并
Requires
- php: >=5.6.0
Requires (Dev)
- ext-json: *
- phpunit/phpunit: ^9.1
README
这是一个简单的库,用于简化两个或更多PHP stdClass
对象属性的合并
非递归
合并两个对象的最快方法是将...$others
列表中存在的字段应用到根对象上。
$o1 = json_decode('{"key": "value"}'); $o2 = json_decode('{"key2": "value2"}'); $o3 = json_decode('{"key3": "value3"}'); $out = object_merge($o1, $o2, $o3); var_dump($out); /* class stdClass#55 (3) { public $key => string(5) "value" public $key2 => string(6) "value2" public $key3 => string(6) "value3" } */
递归
如果您需要递归合并子对象,这也是可能的。
$o1 = json_decode('{"key": ["one"]}'); $o2 = json_decode('{"key": ["two"]}'); $o3 = json_decode('{"key": ["three"]}'); $out = object_merge_recursive($o1, $o2, $o3); var_dump($out); /* class stdClass#56 (1) { public $key => array(3) { [0] => string(3) "one" [1] => string(3) "two" [2] => string(5) "three" } } */
回调
如果您希望有时手动处理两个值的合并,可以使用提供的_callback
函数。
回调提供
您可以提供任何您想要的php-callable表示法,包括
object_merge_callback(0, 'function_name', ...$objects); object_merge_callback(0, $closure, ...$objects); object_merge_callback(0, ['FQN', 'function_name'], ...$objects); object_merge_callback(0, [$instance, 'function_name'], ...$objects);
回调参数
回调函数将恰好提供一个参数,并且它始终是ObjectMergeState的实例。
回调响应
如果回调函数返回ObjectMergeResult以外的任何内容,它将直接用作合并的值,而无需进一步处理或递归。
有关如何处理每个参数的说明,请参阅ObjectMergeResult上的注释。
use DCarbone\ObjectMergeResult; use DCarbone\ObjectMergeState; /** * @param ObjectMergeState $state * @return ObjectMergeResult|null */ function merge_int_to_null(ObjectMergeState $state) { if (is_int($state->leftValue)) { return null; } return new ObjectMergeResult(true); } /** * @return ObjectMergeResult */ function merge_always_continue() { return new ObjectMergeResult(true); } /** * @param ObjectMergeState $state * @return mixed */ function merge_use_left_side(ObjectMergeState $state) { return $state->leftValue; } $o1 = json_decode('{"int1":1,"str1":"string","int2":2,"float":3.2,"arr":[]}'); $o2 = json_decode('{"int1":-3432,"str1":"sandwiches","int2":' . PHP_INT_MAX . ',"float":2.3,"arr":["onevalue"]}'); $out1 = object_merge_callback(0, 'merge_int_to_null', $o1, $o2); $out2 = object_merge_callback(0, 'merge_always_continue', $o1, $o2); $out3 = object_merge_callback(0, 'merge_use_left_side', $o1, $o2); var_dump($out1); /* class stdClass#87 (5) { public $int1 => NULL public $str1 => string(10) "sandwiches" public $int2 => NULL public $float => double(2.3) public $arr => array(1) { [0] => string(8) "onevalue" } } */ var_dump($out2); /* class stdClass#160 (5) { public $int1 => int(-3432) public $str1 => string(10) "sandwiches" public $int2 => int(9223372036854775807) public $float => double(2.3) public $arr => array(1) { [0] => string(8) "onevalue" } } */ var_dump($out3); /* class stdClass#123 (5) { public $int1 => int(1) public $str1 => string(6) "string" public $int2 => int(2) public $float => double(3.2) public $arr => array(0) { } } */
合并选项
object_merge
和object_merge_recursive
函数有同名的姐妹函数object_merge_opts
和object_merge_recursive_opts
。每个这些都有必须是一个包含您所需选项的位或运算的必需的$opts
参数。
OBJECT_MERGE_OPT_CONFLICT_OVERWRITE
这是默认选项。
这意味着当提供的根对象已经有一个在...$others
中看到的字段时,最终将使用$others
对象的最后一个值。
示例
$o1 = json_decode('{"key":'.PHP_INT_MAX.'}'); $o2 = json_decode('{"key":true'); $o3 = json_decode('{"key":"not a number"}'); $out = object_merge($o1, $o2, $o3); var_dump($out); /* class stdClass#56 (1) { public $key => string(12) "not a number" } */
OBJECT_MERGE_OPT_CONFLICT_EXCEPTION
当提供此选项时,如果存在类型不匹配,将引发异常。
示例
$o1 = json_decode('{"key":'.PHP_INT_MAX.'}'); $o2 = json_decode('{"key":true'); $o3 = json_decode('{"key":"not a number"}'); $out = object_merge_opts(OBJECT_MERGE_OPT_CONFLICT_EXCEPTION, $o1, $o2, $o3); // UnexpectedValueException thrown
OBJECT_MERGE_OPT_UNIQUE_ARRAYS
注意:这仅在执行递归合并时才有影响!
当提供此选项时,任何没有与现有字段类型冲突的数组值将通过array_values(array_unique($v))
传递。
这实际上会返回一个重新索引的数组,其中只包含唯一值。
示例
$o1 = json_decode('{"key":["one"]}'); $o2 = json_decode('{"key":["one","two"]}'); $o3 = json_decode('{"key":["one","two","three"]}'); $out = object_merge_recursive_opts(OBJECT_MERGE_OPT_UNIQUE_ARRAYS, $o1, $o2, $o3); var_dump($out); /* class stdClass#57 (1) { public $key => array(3) { [0] => string(3) "one" [1] => string(3) "two" [2] => string(5) "three" } } */
OBJECT_MERGE_OPT_COMPARE_ARRAYS
注意:这仅在递归合并期间才有影响!
当提供此选项时,将比较并合并单个数组偏移量的值,而不仅仅是简单地将它们附加在一起。
示例 1
$o1 = json_decode('{"arr":[{"key1":"value1"}]}'); $o2 = json_decode('{"arr":[{"key2":"value2"}]}'); $o3 = json_decode('{"arr":[{"key3":"value3"}]}'); $out = object_merge_recursive_opts(OBJECT_MERGE_OPT_MERGE_ARRAY_VALUES, $o1, $o2, $o3); var_dump($out); /* class stdClass#120 (1) { public $arr => array(1) { [0] => class stdClass#116 (3) { public $key1 => string(6) "value1" public $key2 => string(6) "value2" public $key3 => string(6) "value3" } } } */
示例 2
$o1 = json_decode('{"arr":[{"key1":"value1","arr":[{"key11":"value11"}]}]}'); $o2 = json_decode('{"arr":[{"key2":"value2","arr":[{"key22":"value22"}]}]}'); $o3 = json_decode('{"arr":[{"key3":"value3","arr":[{"key33":"value33"}]}]}'); $out = object_merge_recursive_opts(OBJECT_MERGE_OPT_MERGE_ARRAY_VALUES, $o1, $o2, $o3); var_dump($out); /* class stdClass#56 (1) { public $arr => array(1) { [0] => class stdClass#107 (4) { public $key1 => string(6) "value1" public $arr => array(1) { [0] => class stdClass#119 (3) { public $key11 => string(7) "value11" public $key22 => string(7) "value22" public $key33 => string(7) "value33" } } public $key2 => string(6) "value2" public $key3 => string(6) "value3" } } } */
OBJECT_MERGE_OPT_NULL_AS_UNDEFINED
当指定时,NULL值被视为UNDEFINED,这意味着它们不会引发类型冲突,并且将使用非空值进行合并。
如果您不希望将所有类型冲突都覆盖为右侧值,但希望忽略null到非null的差异,这很有用。
示例
$o1 = json_decode('{"key":"value"}'); $o2 = json_decode('{"key":null}'); $o3 = json_decode('{"key":"different value"}'); $out = object_merge_recursive_opts(OBJECT_MERGE_OPT_NULL_AS_UNDEFINED, $o1, $o2, $o3); var_dump($out); /* class stdClass#161 (1) { public $key => string(15) "different value" } */