dcarbone/php-object-merge

PHP对象属性合并

v2.2.0 2020-07-27 17:56 UTC

This package is auto-updated.

Last update: 2024-08-28 03:42:40 UTC


README

这是一个简单的库,用于简化两个或更多PHP stdClass对象属性的合并

Build Status

非递归

合并两个对象的最快方法是将...$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_mergeobject_merge_recursive函数有同名的姐妹函数object_merge_optsobject_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"
}
*/