Skip to content
← Back to Functions
Code

Recursive Array Diff Reporter

Compares nested arrays and reports added, removed, and changed paths.

Function signature

ogCompareNestedArrays(old_data, new_data, prefix = '')

Categories

  • File and Upload Safety

Parameters

old_dataOriginal array.new_dataNew array.prefixInternal path prefix for recursive comparison.

Return value

Short public-safe status message.

  • added
  • removed
  • changed

Compatibility

Existing function name and call order preserved; metadata signature corrected to source.

Minimum PHP version: 7.4

Security notes

Validate request method, identity, permissions, and caller-owned allowlists before use; keep secrets and internal paths out of public output.

Code

<?php

/*
 * Copyright (c) 2026 Jeffery L. Paris <jparis@phpog.com>.
 * Free for personal and internal use. Paid project use requires visible credit
 * to Jeffery L. Paris. Corporate use requires a paid license fee unless a
 * separate written license states otherwise.
 */

/**
 * Compares nested arrays and reports added, removed, and changed paths.
 *
 * Primary use case: Config audits, API response checks.
 * Typical inputs: old array, new array.
 * Typical output: change report array.
 *
 * Implementation note: Normalize scalar types before comparison if needed.
 *
 * @param array $old_data Original array.
 * @param array $new_data New array.
 * @param string $prefix Internal path prefix for recursive comparison.
 * @return array Structured comparison report.
 */
function ogCompareNestedArrays($old_data, $new_data, $prefix = '') {
	$result = array(
		'success' => false,
		'message' => '',
		'data' => array()
	);

	if (!is_array($old_data) || !is_array($new_data)) {
		$result['message'] = 'Both comparison values must be arrays.';
		return $result;
	}

	$added = array();
	$removed = array();
	$changed = array();
	$keys = array_unique(array_merge(array_keys($old_data), array_keys($new_data)));

	foreach ($keys as $key) {
		$path = (string)$key;
		if ($prefix !== '') {
			$path = $prefix . '.' . $path;
		}

		$old_has_key = array_key_exists($key, $old_data);
		$new_has_key = array_key_exists($key, $new_data);

		if (!$old_has_key && $new_has_key) {
			$added[$path] = $new_data[$key];
			continue;
		}

		if ($old_has_key && !$new_has_key) {
			$removed[$path] = $old_data[$key];
			continue;
		}

		if (is_array($old_data[$key]) && is_array($new_data[$key])) {
			$child = ogCompareNestedArrays($old_data[$key], $new_data[$key], $path);
			if (!empty($child['data']['added'])) {
				$added = array_merge($added, $child['data']['added']);
			}
			if (!empty($child['data']['removed'])) {
				$removed = array_merge($removed, $child['data']['removed']);
			}
			if (!empty($child['data']['changed'])) {
				$changed = array_merge($changed, $child['data']['changed']);
			}
			continue;
		}

		if ($old_data[$key] !== $new_data[$key]) {
			$changed[$path] = array(
				'old' => $old_data[$key],
				'new' => $new_data[$key]
			);
		}
	}

	$result['success'] = true;
	$result['message'] = 'Nested arrays compared.';
	$result['data'] = array(
		'added' => $added,
		'removed' => $removed,
		'changed' => $changed,
		'change_count' => count($added) + count($removed) + count($changed)
	);

	return $result;
}