compare object properties and show diff in PHP compare object properties and show diff in PHP php php

compare object properties and show diff in PHP


Something like the following, which iterates through and does a recursive diff is the item in the array is itself an array could work:

Des similar work to array_diff, but it does a check to see if it is an array first (is_array) and if so, sets the diff for that key to be the diff for that array. Repeats recursively.

function recursive_array_diff($a1, $a2) {     $r = array();     foreach ($a1 as $k => $v) {        if (array_key_exists($k, $a2)) {             if (is_array($v)) {                 $rad = recursive_array_diff($v, $a2[$k]);                 if (count($rad)) { $r[$k] = $rad; }             } else {                 if ($v != $a2[$k]) {                     $r[$k] = $v;                 }            }        } else {             $r[$k] = $v;         }     }     return $r; }

It then works like this:

$obj1 = new StdClass; $obj1->prop = array(1,2);$obj2 = new StdClass; $obj2->prop = array(1,3);print_r(recursive_array_diff((array)$obj1, (array)$obj2));/* Output:    Array    (        [prop] => Array            (                [1] => 2            )    )*/


My solution will recursively diff a stdClass and all it nested arrays and stdClass objects.It is meant to be used for comparison of rest api responses.

function objDiff($obj1, $obj2):array {     $a1 = (array)$obj1;    $a2 = (array)$obj2;    return arrDiff($a1, $a2);}function arrDiff(array $a1, array $a2):array {    $r = array();    foreach ($a1 as $k => $v) {        if (array_key_exists($k, $a2)) {             if ($v instanceof stdClass) {                 $rad = objDiff($v, $a2[$k]);                 if (count($rad)) { $r[$k] = $rad; }             }else if (is_array($v)){                $rad = arrDiff($v, $a2[$k]);                  if (count($rad)) { $r[$k] = $rad; }             // required to avoid rounding errors due to the             // conversion from string representation to double            } else if (is_double($v)){                 if (abs($v - $a2[$k]) > 0.000000000001) {                     $r[$k] = array($v, $a2[$k]);                 }            } else {                 if ($v != $a2[$k]) {                     $r[$k] = array($v, $a2[$k]);                 }            }        } else {             $r[$k] = array($v, null);         }     }     return $r;     } 

Here is a comparison function that I built using the pattern:

function objEq(stdClass $obj1, stdClass $obj2):bool {     $a1 = (array)$obj1;    $a2 = (array)$obj2;    return arrEq($a1, $a2);}function arrEq(array $a1, array $a2):bool {    foreach ($a1 as $k => $v) {        if (array_key_exists($k, $a2)) {             if ($v instanceof stdClass) {                 $r = objEq($v, $a2[$k]);                 if ($r === false) return false;             }else if (is_array($v)){                $r = arrEq($v, $a2[$k]);                  if ($r === false) return false;             } else if (is_double($v)){             // required to avoid rounding errors due to the             // conversion from string representation to double                if (abs($v - $a2[$k]) > 0.000000000001) {                     return false;                 }            } else {                 if ($v != $a2[$k]) {                     return false;                 }            }        } else {             return false;         }     }     return true;     }

Usage:

$apiResponse = apiCall(GET, $objId);$responseObj = json_decode($apiResponse);// do stuff ...if(!objEq($myObj, $responseObj) apiCall(PUT, $myObj, $objId);

Note that the apiCall function is just a mock to illustrate the concept.Also this solution is incomplete because it does not take into account any key->value pairs that are unique to obj2. In my use case this is not required and could be neglected.

NB: I borrowed heavily from Peter Hamiltons contribution. If you like what I did then please upvote his solution. Thanks!