Welcome

カキノタblog

自分の興味あるテーマを中心に、図解多めに記事を作成していきたいと思います。

Tips オブジェクトをマージ(deep merge)する

オブジェクトをマージする方法はいろいろあります。しかし再帰的に上書きしながらdeep copyするものがなかなかなかったのを見つけたので転載させて貰っちゃいます(感謝!)。

class Utils {

    /**
     * Recursively merges two objects and returns a resulting object.
     * @param object $obj1 The base object
     * @param object $obj2 The merge object
     * @return object The merged object
     */
    public function mergeObjectsRecursively($obj1, $obj2)
    {
        $merged = $this->_mergeRecursively($obj1, $obj2);
        return $merged;
    }

    /**
     * Recursively merges two objects and returns a resulting object.
     * @param object $obj1 The base object
     * @param object $obj2 The merge object
     * @return object The merged object
     */
    private function _mergeRecursively($obj1, $obj2) {
        if (is_object($obj2)) {
            $keys = array_keys(get_object_vars($obj2));
            foreach ($keys as $key) {
                if (
                    isset($obj1->{$key})
                    && is_object($obj1->{$key})
                    && is_object($obj2->{$key})
                ) {
                    $obj1->{$key} = $this->_mergeRecursively($obj1->{$key}, $obj2->{$key});
                } elseif (isset($obj1->{$key})
                && is_array($obj1->{$key})
                && is_array($obj2->{$key})) {
                    $obj1->{$key} = $this->_mergeRecursively($obj1->{$key}, $obj2->{$key});
                } else {
                    $obj1->{$key} = $obj2->{$key};
                }
            }
        } elseif (is_array($obj2)) {
            if (
                is_array($obj1)
                && is_array($obj2)
            ) {
                $obj1 = array_merge_recursive($obj1, $obj2);
            } else {
                $obj1 = $obj2;
            }
        }

        return $obj1;
    }
}

$utils = new Utils();

$obj1 = (object) [
    'debug' => true,
    'modules' => [
        'Module1'
    ],
    'routes' => (object) [
        'test' => '/my-tests',
        'override' => 'false',
        'test2' => (object) [
            'override' => 'false',
            'shouldStay' => 'true'
        ]
    ]
];

$obj2 = (object) [
    'debug' => false,
    'modules' => [
        'Module2',
        'Module3'
    ],
    'routes' => (object) [
        'route1' => (object) [
            'path' => '/'
        ],
        'override' => 'true',
        'test2' => (object) [
            'override' => 'true'
        ]
    ]
];

$obj3 = $utils->mergeObjectsRecursively($obj1, $obj2);

echo "<pre>";
print_r($obj3);
echo "</pre>";

(出典)https://dev.to/joshualjohnson/tutorial-how-to-recursively-merge-two-objects-in-php-3jf9

参考リンク