如何获取PHP中多维数组之间的增删改查?

How to retrieve updates, deletions, and additions between multi-dimensional arrays in PHP?

我有 2 个多维数组。本质上,其中之一是一个不断更新的数组。我想找到数组之间的更新,也就是添加和删除。例如,我有一些数据如下:

Updated/new 数组(数组#1):

Array
(
    [CN=Joe Dope,CN=Users,DC=test,DC=io] => Array
        (

            [msexchassistantname] => cn=CIGdeadp1,cn=Users,dc=test,dc=io
            [memberof] => Array
                (
                    [0] => CN=CIGdeadp1,CN=Users,DC=test,DC=io
                    [1] => CN=CASUsers,CN=Users,DC=test,DC=io
                    [2] => CN=CloudNCUsers,CN=Users,DC=test,DC=io
                    [3] => CN=CloudEmailUsers,CN=Users,DC=test,DC=io
                )

            [whenchanged] => 20201004180306.0Z
            [usnchanged] => 33404
            [distinguishedname] => CN=Joe Dope,CN=Users,DC=test,DC=io
        )

    [CN=Ronald,CN=Users,DC=test,DC=io] => Array
      (
          [usnchanged] => 1342
          [whenchanged] => 20191106190201.0Z
      )
)

旧数组(数组#2):

   [CN=Joe Dope,CN=Users,DC=test,DC=io] => Array
        (

            [msexchassistantname] => cn=CIGdeadp1,cn=Users,dc=test,dc=io
            [memberof] => Array
                (
                    [0] => CN=CIGdeadp1,CN=Users,DC=test,DC=io
                    [1] => CN=CASUsers,CN=Users,DC=test,DC=io
                    [2] => CN=CloudNCUsers,CN=Users,DC=test,DC=io
                    [3] => CN=CloudOfficeUsers,CN=Users,DC=test,DC=io
                )

            [othermailbox] => Array
                (
                    [0] => jdope1@gmail.com
                    [1] => foobar@gmail.com
                )

            [whenchanged] => 20200929142821.0Z
            [usnchanged] => 32855
            [distinguishedname] => CN=Joe Dope,CN=Users,DC=test,DC=io
        )

到目前为止我所做的如下:

$array = [];
$array["CN=Joe Dope,CN=Users,DC=test,DC=io"] = array("msexchassistantname" => ("cn=CIGdeadp1,cn=Users,dc=test,dc=io"),
"memberof" => array("0" => "CN=CIGdeadp1,CN=Users,DC=test,DC=io", "1" => "CN=CASUsers,CN=Users,DC=test,DC=io",
"2" => "CN=CloudNCUsers,CN=Users,DC=test,DC=io", "3" => "CN=CloudEmailUsers,CN=Users,DC=test,DC=io"
), "whenchanged" => "20201004180306.0Z", "usnchanged" => "33404", "distinguishedname" => "CN=Joe Dope,CN=Users,DC=test,DC=io");

$array["CN=Ronald,CN=Users,DC=test,DC=io"] = array("usnchanged" => "1342", "whenchanged" => "20191106190201.0Z");


$array2 = [];
$array2["CN=Joe Dope,CN=Users,DC=test,DC=io"] = array("msexchassistantname" => "cn=CIGdeadp1,cn=Users,dc=test,dc=io",
"memberof" => array("0" => "CN=CIGdeadp1,CN=Users,DC=test,DC=io", "1" => "CN=CASUsers,CN=Users,DC=test,DC=io", "2" => "CN=CloudNCUsers,CN=Users,DC=test,DC=io",
"3" => "CN=CloudOfficeUsers,CN=Users,DC=test,DC=io"), "othermailbox" => array("0" => "jdope1@gmail.com", "1" => "foobar@gmail.com"), "whenchanged" => "20200929142821.0Z", "usnchanged" => "32855", "distinguishedname" => "CN=Joe Dope,CN=Users,DC=test,DC=io");



function check_diff_multi($array1, $array2){
    $result = array();

    foreach($array1 as $key => $val) {
        if(is_array($val) && isset($array2[$key])) {
            $tmp = check_diff_multi($val, $array2[$key]);
            if($tmp) {
                $result[$key] = $tmp;
            }
        }
        elseif(!isset($array2[$key])) {
            $result[$key] = null;
        }
        elseif($val !== $array2[$key]) {
            $result[$key] = $array2[$key];
        }

        if(isset($array2[$key])) {
            unset($array2[$key]);
        }
    }

    $result = array_merge($result, $array2);

    return $result;
}

$full_difference = array_merge(check_diff_multi($array, $array2), check_diff_multi($array2, $array));
print_r($full_difference);

这没有给我想要的确切输出。

这是它给我的输出:

Array
(
    [CN=Joe Dope,CN=Users,DC=test,DC=io] => Array
        (
            [memberof] => Array
                (
                    [0] => CN=CloudEmailUsers,CN=Users,DC=test,DC=io
                )

            [othermailbox] => 
            [whenchanged] => 20201004180306.0Z
            [usnchanged] => 33404
            [distinguishedname] => CN=Joe Dope,CN=Users,DC=test,DC=io
        )

    [CN=Ronald,CN=Users,DC=test,DC=io] => Array
        (
            [usnchanged] => 1342
            [whenchanged] => 20191106190201.0Z
        )

)

我想要的是更像这样的东西:

Array
(
    [CN=Joe Dope,CN=Users,DC=test,DC=io] => Array
        (
            [memberof] => Array
                (
                    [3] => CN=CloudOfficeUsers,CN=Users,DC=test,DC=io (Deleted)
                    [3] => CN=CloudEmailUsers,CN=Users,DC=test,DC=io (Updated)
                )

            [othermailbox] => Array (Deleted)
                (
                    [0] => jdope1@gmail.com (Deleted)
                    [1] => foobar@gmail.com (Deleted)
                )
            [whenchanged] => 20201004180306.0Z (Added)
            [whenchanged] => 20200929142821.0Z (Deleted)
            [usnchanged] => 33404 (Added)
            [usnchanged] => 32855 (Deleted)
        )

    [CN=Ronald,CN=Users,DC=test,DC=io] => Array (Added)
        (
            [usnchanged] => 1342 (Added)
            [whenchanged] => 20191106190201.0Z (Added)
        )

)

非常感谢任何帮助。谢谢!

编辑:

忘记为多维数组中的数组是否具有相同的值添加边缘情况。

<?php
$array[ "CN=Joe Dope,CN=Users,DC=test,DC=io" ] = array(
    "msexchassistantname" => ( "cn=CIGdeadp1,cn=Users,dc=test,dc=io" ),
    "memberof" => array(
        "0" => "CN=CIGdeadp1,CN=Users,DC=test,DC=io",
        "1" => "CN=CASUsers,CN=Users,DC=test,DC=io",
        "2" => "CN=CloudNCUsers,CN=Users,DC=test,DC=io",
        "3" => "CN=CloudEmailUsers,CN=Users,DC=test,DC=io"
    ),
    "objectclass" => array(
      "0" => "top",
      "1" => "person"
    ),
    "whenchanged" => "20201004180306.0Z",
    "usnchanged" => "33404",
    "distinguishedname" => "CN=Joe Dope,CN=Users,DC=test,DC=io"
);

$array[ "CN=Ronald,CN=Users,DC=test,DC=io" ] = array(
    "usnchanged" => "1342",
    "whenchanged" => "20191106190201.0Z"
);

$array2[ "CN=Joe Dope,CN=Users,DC=test,DC=io" ] = array(
    "msexchassistantname" => "cn=CIGdeadp1,cn=Users,dc=test,dc=io",
    "memberof" => array(
        "0" => "CN=CIGdeadp1,CN=Users,DC=test,DC=io",
        "1" => "CN=CASUsers,CN=Users,DC=test,DC=io",
        "2" => "CN=CloudNCUsers,CN=Users,DC=test,DC=io",
        "3" => "CN=CloudOfficeUsers,CN=Users,DC=test,DC=io"
    ),
    "objectclass" => array(
      "0" => "top",
      "1" => "person"
    ),
    "othermailbox" => array(
        "0" => "jdope1@gmail.com",
        "1" => "foobar@gmail.com"
    ),
    "whenchanged" => "20200929142821.0Z",
    "usnchanged" => "32855",
    "distinguishedname" => "CN=Joe Dope,CN=Users,DC=test,DC=io"
);
# Main recursive function to compare
function recordChanges($old, $new, &$result)
{
    # Loop through the old array to see what is removed
    foreach($old as $k => $v) {
        # If the old and new have the same key
        if(isset($new[$k])) {
            # If array, recurse the array
            if(is_array($v)) {
                recordChanges($old[$k], $new[$k], $result[$k]);
            }
            # Note if the old is different
            else {
                $append =   ($old[$k] == $new[$k])? "" : " (Deleted)";

                if(!empty($append))
                    $result[$k.$append] =   $v;
            }
        }
        # Note a straight delete
        else {
            $d  =   ' (Deleted)';
            $nk =   (is_array($v))? $k.$d : $k;
            $result[$nk] =   (is_array($v))? appendKeys($v, $d) : $v.$d;
        }
    }
    # Now go through the new array
    foreach($new as $k => $v) {
        # See if there is a matching old array
        if(isset($old[$k])) {
            # Recurse for changes
            if(is_array($v)) {
                recordChanges($old[$k], $new[$k], $result[$k]);
            }
            # If not in old, note update
            else {
                $append =   ($old[$k] == $new[$k])? "" : " (Updated)";

                if(!empty($append))
                    $result[$k.$append] =   $v;
            }
        }
        # If not in old, note as new
        else {
            $d  =   ' (Added)';
            $nk =   (is_array($v))? $k.$d : $k;
            $result[$nk] =   (is_array($v))? appendKeys($v, $d) : $v.$d;
        }

        ksort($result);
    }
}
# This will just do a full recurse and append without any conditions
function appendKeys($array, $append)
{
    $new    =   [];
    foreach($array as $k => $v) {
        $nk =   (is_array($v))? $k.$append : $k;
        $new[$nk]    =   (is_array($v))? appendKeys($v, $append) : $v.$append;
    }
    ksort($new);
    return $new;
}

$result =   [];
recordChanges($array2, $array, $result);
print_r($result);
?>

所以现在我们有 2 个在每个数组中都相同的对象类。根据 运行 代码,我们得到以下内容:

Array
(
    [CN=Joe Dope,CN=Users,DC=test,DC=io] => Array
        (
            [memberof] => Array
                (
                    [3 (Deleted)] => CN=CloudOfficeUsers,CN=Users,DC=test,DC=io
                    [3 (Updated)] => CN=CloudEmailUsers,CN=Users,DC=test,DC=io
                )

            [objectclass] => 
            [othermailbox (Deleted)] => Array
                (
                    [0] => jdope1@gmail.com (Deleted)
                    [1] => foobar@gmail.com (Deleted)
                )

            [usnchanged (Deleted)] => 32855
            [usnchanged (Updated)] => 33404
            [whenchanged (Deleted)] => 20200929142821.0Z
            [whenchanged (Updated)] => 20201004180306.0Z
        )

    [CN=Ronald,CN=Users,DC=test,DC=io (Added)] => Array
        (
            [usnchanged] => 1342 (Added)
            [whenchanged] => 20191106190201.0Z (Added)
        )

)

如果我们能删除 [objectclass] => 就好了。

您可能可以使用递归数组迭代器来完成此操作,但我只使用了几个函数。第一个函数 recordChanges() 可以重构,因为上半部分使用与下半部分(基本上)相同的逻辑,但你明白了:

<?php
$array[ "CN=Joe Dope,CN=Users,DC=test,DC=io" ] = array(
    "msexchassistantname" => ( "cn=CIGdeadp1,cn=Users,dc=test,dc=io" ),
    "memberof" => array(
        "0" => "CN=CIGdeadp1,CN=Users,DC=test,DC=io",
        "1" => "CN=CASUsers,CN=Users,DC=test,DC=io",
        "2" => "CN=CloudNCUsers,CN=Users,DC=test,DC=io",
        "3" => "CN=CloudEmailUsers,CN=Users,DC=test,DC=io"
    ),
    "whenchanged" => "20201004180306.0Z",
    "usnchanged" => "33404",
    "distinguishedname" => "CN=Joe Dope,CN=Users,DC=test,DC=io"
);

$array[ "CN=Ronald,CN=Users,DC=test,DC=io" ] = array(
    "usnchanged" => "1342",
    "whenchanged" => "20191106190201.0Z"
);

$array2[ "CN=Joe Dope,CN=Users,DC=test,DC=io" ] = array(
    "msexchassistantname" => "cn=CIGdeadp1,cn=Users,dc=test,dc=io",
    "memberof" => array(
        "0" => "CN=CIGdeadp1,CN=Users,DC=test,DC=io",
        "1" => "CN=CASUsers,CN=Users,DC=test,DC=io",
        "2" => "CN=CloudNCUsers,CN=Users,DC=test,DC=io",
        "3" => "CN=CloudOfficeUsers,CN=Users,DC=test,DC=io"
    ),
    "othermailbox" => array(
        "0" => "jdope1@gmail.com",
        "1" => "foobar@gmail.com" 
    ),
    "whenchanged" => "20200929142821.0Z",
    "usnchanged" => "32855",
    "distinguishedname" => "CN=Joe Dope,CN=Users,DC=test,DC=io"
);
# Main recursive function to compare
function recordChanges($old, $new, &$result)
{
    # Loop through the old array to see what is removed
    foreach($old as $k => $v) {
        # If the old and new have the same key
        if(isset($new[$k])) {
            # If array, recurse the array
            if(is_array($v)) {
                recordChanges($old[$k], $new[$k], $result[$k]);
            }
            # Note if the old is different
            else {
                $append =   ($old[$k] == $new[$k])? "" : " (Deleted)";
                
                if(!empty($append))
                    $result[$k.$append] =   $v;
            }
        }
        # Note a straight delete
        else {
            $d  =   ' (Deleted)';
            $nk =   (is_array($v))? $k.$d : $k;
            $result[$nk] =   (is_array($v))? appendKeys($v, $d) : $v.$d;
        }
    }
    # Now go through the new array
    foreach($new as $k => $v) {
        # See if there is a matching old array
        if(isset($old[$k])) {
            # Recurse for changes
            if(is_array($v)) {
                recordChanges($old[$k], $new[$k], $result[$k]);
            }
            # If not in old, note update
            else {
                $append =   ($old[$k] == $new[$k])? "" : " (Updated)";
                
                if(!empty($append))
                    $result[$k.$append] =   $v;
            }
        }
        # If not in old, note as new
        else {
            $d  =   ' (Added)';
            $nk =   (is_array($v))? $k.$d : $k;
            $result[$nk] =   (is_array($v))? appendKeys($v, $d) : $v.$d;
        }
        
        ksort($result);
    }
}
# This will just do a full recurse and append without any conditions
function appendKeys($array, $append)
{
    $new    =   [];
    foreach($array as $k => $v) {
        $nk =   (is_array($v))? $k.$append : $k;
        $new[$nk]    =   (is_array($v))? appendKeys($v, $append) : $v.$append;
    }
    ksort($new);
    return $new;
}

$result =   [];
recordChanges($array2, $array, $result);
print_r($result);

这会给你:

Array
(
    [CN=Joe Dope,CN=Users,DC=test,DC=io] => Array
        (
            [memberof] => Array
                (
                    [3 (Deleted)] => CN=CloudOfficeUsers,CN=Users,DC=test,DC=io
                    [3 (Updated)] => CN=CloudEmailUsers,CN=Users,DC=test,DC=io
                )

            [othermailbox (Deleted)] => Array
                (
                    [0] => jdope1@gmail.com (Deleted)
                    [1] => foobar@gmail.com (Deleted)
                )

            [usnchanged (Deleted)] => 32855
            [usnchanged (Updated)] => 33404
            [whenchanged (Deleted)] => 20200929142821.0Z
            [whenchanged (Updated)] => 20201004180306.0Z
        )

    [CN=Ronald,CN=Users,DC=test,DC=io (Added)] => Array
        (
            [usnchanged] => 1342 (Added)
            [whenchanged] => 20191106190201.0Z (Added)
        )

)

请注意,您不能拥有 same-named 密钥,因为它们会相互覆盖,因此要保留密钥,您必须附加密钥。