PHPackages                             dcarbone/php-object-merge - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. dcarbone/php-object-merge

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

dcarbone/php-object-merge
=========================

Object property merging in PHP

v2.2.0(5y ago)56.0k↓33.3%Apache-2.0PHPPHP &gt;=5.6.0

Since Jun 4Pushed 5y ago2 watchersCompare

[ Source](https://github.com/dcarbone/php-object-merge)[ Packagist](https://packagist.org/packages/dcarbone/php-object-merge)[ Docs](https://github.com/dcarbone/php-object-merge)[ RSS](/packages/dcarbone-php-object-merge/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (5)Dependencies (1)Versions (12)Used By (0)

php-object-merge
================

[](#php-object-merge)

This is a simple library that facilitates the merging of two or more PHP `stdClass` object properties

[![Build Status](https://camo.githubusercontent.com/f9bf442d49e0e4af85c2a465b5165a9ec617e107d26293d013bbe4a3b7ba0504/68747470733a2f2f7472617669732d63692e636f6d2f64636172626f6e652f7068702d6f626a6563742d6d657267652e7376673f6272616e63683d6d6173746572)](https://travis-ci.com/dcarbone/php-object-merge)

Non-Recursive
-------------

[](#non-recursive)

The fastest approach to merging two objects will simply apply the fields present in the list of `...$others`to the root object.

```
$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"
}
*/
```

Recursive
---------

[](#recursive)

If you require recursive merging of child objects, that is also possible:

```
$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
--------

[](#callback)

If you wish to sometimes manually handle the merging of two values, you may do so using the provided `_callback`functions.

### Callback providing

[](#callback-providing)

You may provide any php-callable notation you wish, including:

```
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);
```

### Callback arguments

[](#callback-arguments)

The callback function will be provided exactly one parameter, and it will always be an instance of [ObjectMergeState](./src/ObjectMergeState.php).

### Callback response

[](#callback-response)

If the callback function returns *anything* other than an instance of [ObjectMergeResult](./src/ObjectMergeResult.php), it is used outright as the value of the merge, without further processing or recursion.

See comments on [ObjectMergeResult](./src/ObjectMergeResult.php) for how each parameter is handled.

```
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) {
  }
}
*/
```

Merge Options
-------------

[](#merge-options)

The `object_merge` and `object_merge_recursive` functions have sister functions named `object_merge_opts` and `object_merge_recursive_opts` respectively. Each of these has a required `$opts` argument that must be a bitwise inclusive or of your desired options.

#### `OBJECT_MERGE_OPT_CONFLICT_OVERWRITE`

[](#object_merge_opt_conflict_overwrite)

This is the default option.

This means that when the provided root object already has a field seen in one of the `...$others`, the value of the LAST of the `$others` objects will ultimately be used

Example:

```
$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`

[](#object_merge_opt_conflict_exception)

When this is provided, an exception will be raised if there is a type mismatch

Example:

```
$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`

[](#object_merge_opt_unique_arrays)

*NOTE*: This only has an effect when doing a *recursive* merge!

When this is provided, any seen array value that does not have a type conflict with an existing field type has its value pass through `array_values(array_unique($v))`.

This has the net effect of returning a re-indexed array consisting of only unique values.

Example:

```
$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`

[](#object_merge_opt_compare_arrays)

*NOTE*: This only has an effect during a *recursive* merge!

When this is provided, individual array offsets will have their values compared and merged, rather than merely appended together.

Example 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"
    }
  }
}
*/
```

Example 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`

[](#object_merge_opt_null_as_undefined)

When specified, NULL values are treated as UNDEFINED, meaning they will not cause a type conflict to be risen and the non-null value will be used in the merge.

This can be useful if you do not want to have *all* type conflicts to be overwritten with the right-hand value, but want to ignore null to not null differences.

Example:

```
$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"
}
*/
```

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity27

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~5 days

Recently: every ~13 days

Total

11

Last Release

2121d ago

Major Versions

v1.0.1 → v2.0.02020-06-04

### Community

Maintainers

![](https://www.gravatar.com/avatar/385c0c0eae1b51f1e81ee464ff6bfb3cce32589ac252ca68cc3a8aec2e3ada14?d=identicon)[dcarbone](/maintainers/dcarbone)

---

Top Contributors

[![dcarbone](https://avatars.githubusercontent.com/u/1392439?v=4)](https://github.com/dcarbone "dcarbone (21 commits)")

---

Tags

json-mergeobject-mergeobject-mergingphpphpmergeobject-merge

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/dcarbone-php-object-merge/health.svg)

```
[![Health](https://phpackages.com/badges/dcarbone-php-object-merge/health.svg)](https://phpackages.com/packages/dcarbone-php-object-merge)
```

###  Alternatives

[gehrisandro/tailwind-merge-laravel

TailwindMerge for Laravel merges multiple Tailwind CSS classes by automatically resolving conflicts between them

341682.2k18](/packages/gehrisandro-tailwind-merge-laravel)[gehrisandro/tailwind-merge-php

TailwindMerge for PHP merges multiple Tailwind CSS classes by automatically resolving conflicts between them

1391.5M9](/packages/gehrisandro-tailwind-merge-php)[imanghafoori/laravel-anypass

A minimal yet powerful package to help you in development.

21421.6k](/packages/imanghafoori-laravel-anypass)[nlac/nlsclientscript

Yii ClientScript extension for prevent reloading javascript and merging/minfying resources

208.2k](/packages/nlac-nlsclientscript)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
