PHP MD5多维数组最好的方法?

发布于 2024-08-21 06:35:09 字数 150 浏览 21 评论 0原文

生成多维数组的 MD5(或任何其他哈希值)的最佳方法是什么?

我可以轻松编写一个循环,遍历数组的每个级别,将每个值连接成一个字符串,然后简单地对字符串执行 MD5。

然而,这充其量看起来很麻烦,我想知道是否有一个时髦的函数可以接受多维数组并对其进行散列。

What is the best way to generate an MD5 (or any other hash) of a multi-dimensional array?

I could easily write a loop which would traverse through each level of the array, concatenating each value into a string, and simply performing the MD5 on the string.

However, this seems cumbersome at best and I wondered if there was a funky function which would take a multi-dimensional array, and hash it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

我的黑色迷你裙 2024-08-28 06:35:09

(底部可复制粘贴功能)

如前所述,以下内容将起作用。

md5(serialize($array));

然而,值得注意的是(具有讽刺意味的是)json_encode 的执行速度明显更快:

md5(json_encode($array));

事实上,速度增加了两倍,因为 (1) json_encode 单独的执行速度比序列化更快,并且 (2) json_encode 生成字符串较小,因此 md5 需要处理的内容较少。

编辑:以下是支持这一说法的证据:

<?php //this is the array I'm using -- it's multidimensional.
$array = unserialize('a:6:{i:0;a:0:{}i:1;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:0:{}}}i:2;s:5:"hello";i:3;a:2:{i:0;a:0:{}i:1;a:0:{}}i:4;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:0:{}}}}}}}i:5;a:5:{i:0;a:0:{}i:1;a:4:{i:0;a:0:{}i:1;a:0:{}i:2;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:0:{}}i:3;a:6:{i:0;a:0:{}i:1;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:0:{}}}i:2;s:5:"hello";i:3;a:2:{i:0;a:0:{}i:1;a:0:{}}i:4;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:0:{}}}}}}}i:5;a:5:{i:0;a:0:{}i:1;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:0:{}}}i:2;s:5:"hello";i:3;a:2:{i:0;a:0:{}i:1;a:0:{}}i:4;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:0:{}}}}}}}}}}i:2;s:5:"hello";i:3;a:2:{i:0;a:0:{}i:1;a:0:{}}i:4;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:0:{}}}}}}}}}');

//The serialize test
$b4_s = microtime(1);
for ($i=0;$i<10000;$i++) {
    $serial = md5(serialize($array));
}
echo 'serialize() w/ md5() took: '.($sTime = microtime(1)-$b4_s).' sec<br/>';

//The json test
$b4_j = microtime(1);
for ($i=0;$i<10000;$i++) {
    $serial = md5(json_encode($array));
}
echo 'json_encode() w/ md5() took: '.($jTime = microtime(1)-$b4_j).' sec<br/><br/>';
echo 'json_encode is <strong>'.( round(($sTime/$jTime)*100,1) ).'%</strong> faster with a difference of <strong>'.($sTime-$jTime).' seconds</strong>';

JSON_ENCODE 始终快 250% (2.5 倍) 以上(通常超过 300%)——这不是一个微不足道的差异。您可以在此处查看使用此实时脚本的测试结果:

现在,需要注意的一件事是 array(1,2,3) 将生成与 array(3,2,1) 不同的 MD5。 如果这不是您想要的。尝试以下代码:

//Optionally make a copy of the array (if you want to preserve the original order)
$original = $array;

array_multisort($array);
$hash = md5(json_encode($array));

编辑: 有人质疑颠倒顺序是否会产生相同的结果。所以,我在这里(正确)做到了:

正如你所看到的,结果是完全一样的。这是(更正)测试最初由 Drupal 相关人员创建

为了更好地衡量,这里有一个函数/方法,您可以复制粘贴(在5.3.3-1ubuntu9.5中测试):

function array_md5(Array $array) {
    //since we're inside a function (which uses a copied array, not 
    //a referenced array), you shouldn't need to copy the array
    array_multisort($array);
    return md5(json_encode($array));
}

(Copy-n-paste-able function at the bottom)

As mentioned prior, the following will work.

md5(serialize($array));

However, it's worth noting that (ironically) json_encode performs noticeably faster:

md5(json_encode($array));

In fact, the speed increase is two-fold here as (1) json_encode alone performs faster than serialize, and (2) json_encode produces a smaller string and therefore less for md5 to handle.

Edit: Here is evidence to support this claim:

<?php //this is the array I'm using -- it's multidimensional.
$array = unserialize('a:6:{i:0;a:0:{}i:1;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:0:{}}}i:2;s:5:"hello";i:3;a:2:{i:0;a:0:{}i:1;a:0:{}}i:4;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:0:{}}}}}}}i:5;a:5:{i:0;a:0:{}i:1;a:4:{i:0;a:0:{}i:1;a:0:{}i:2;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:0:{}}i:3;a:6:{i:0;a:0:{}i:1;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:0:{}}}i:2;s:5:"hello";i:3;a:2:{i:0;a:0:{}i:1;a:0:{}}i:4;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:0:{}}}}}}}i:5;a:5:{i:0;a:0:{}i:1;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:3:{i:0;a:0:{}i:1;a:0:{}i:2;a:0:{}}}i:2;s:5:"hello";i:3;a:2:{i:0;a:0:{}i:1;a:0:{}}i:4;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:0:{}}}}}}}}}}i:2;s:5:"hello";i:3;a:2:{i:0;a:0:{}i:1;a:0:{}}i:4;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:1:{i:0;a:0:{}}}}}}}}}');

//The serialize test
$b4_s = microtime(1);
for ($i=0;$i<10000;$i++) {
    $serial = md5(serialize($array));
}
echo 'serialize() w/ md5() took: '.($sTime = microtime(1)-$b4_s).' sec<br/>';

//The json test
$b4_j = microtime(1);
for ($i=0;$i<10000;$i++) {
    $serial = md5(json_encode($array));
}
echo 'json_encode() w/ md5() took: '.($jTime = microtime(1)-$b4_j).' sec<br/><br/>';
echo 'json_encode is <strong>'.( round(($sTime/$jTime)*100,1) ).'%</strong> faster with a difference of <strong>'.($sTime-$jTime).' seconds</strong>';

JSON_ENCODE is consistently over 250% (2.5x) faster (often over 300%) -- this is not a trivial difference. You may see the results of the test with this live script here:

Now, one thing to note is array(1,2,3) will produce a different MD5 as array(3,2,1). If this is NOT what you want. Try the following code:

//Optionally make a copy of the array (if you want to preserve the original order)
$original = $array;

array_multisort($array);
$hash = md5(json_encode($array));

Edit: There's been some question as to whether reversing the order would produce the same results. So, I've done that (correctly) here:

As you can see, the results are exactly the same. Here's the (corrected) test originally created by someone related to Drupal:

And for good measure, here's a function/method you can copy and paste (tested in 5.3.3-1ubuntu9.5):

function array_md5(Array $array) {
    //since we're inside a function (which uses a copied array, not 
    //a referenced array), you shouldn't need to copy the array
    array_multisort($array);
    return md5(json_encode($array));
}
落日海湾 2024-08-28 06:35:09
md5(serialize($array));
md5(serialize($array));
澉约 2024-08-28 06:35:09

我通过回答加入了一个非常拥挤的聚会,但有一个重要的考虑因素,现有的答案都没有解决。 json_encode()serialize()的值都取决于数组中元素的顺序!

下面是不排序和排序的结果对两个具有相同值但以不同顺序添加的数组对数组进行排序(帖子底部的代码)

    serialize()
1c4f1064ab79e4722f41ab5a8141b210
1ad0f2c7e690c8e3cd5c34f7c9b8573a

    json_encode()
db7178ba34f9271bfca3a05c5dddf502
c9661c0852c2bd0e26ef7951b4ca9e6f

    Sorted serialize()
1c4f1064ab79e4722f41ab5a8141b210
1c4f1064ab79e4722f41ab5a8141b210

    Sorted json_encode()
db7178ba34f9271bfca3a05c5dddf502
db7178ba34f9271bfca3a05c5dddf502

因此,我推荐给的两种方法 >哈希数组将是:

// You will need to write your own deep_ksort(), or see
// my example below

md5(   serialize(deep_ksort($array)) );

md5( json_encode(deep_ksort($array)) );

json_encode()serialize()的选择应该通过测试<的数据类型来确定em>您正在使用。通过我自己对纯文本和数字数据的测试,如果代码没有运行紧密循环数千次,那么差异甚至不值得进行基准测试。我个人使用 json_encode() 来处理该类型的数据。

这是用于生成上述排序测试的代码:

$a = array();
$a['aa'] = array( 'aaa'=>'AAA', 'bbb'=>'ooo', 'qqq'=>'fff',);
$a['bb'] = array( 'aaa'=>'BBBB', 'iii'=>'dd',);

$b = array();
$b['aa'] = array( 'aaa'=>'AAA', 'qqq'=>'fff', 'bbb'=>'ooo',);
$b['bb'] = array( 'iii'=>'dd', 'aaa'=>'BBBB',);

echo "    serialize()\n";
echo md5(serialize($a))."\n";
echo md5(serialize($b))."\n";

echo "\n    json_encode()\n";
echo md5(json_encode($a))."\n";
echo md5(json_encode($b))."\n";



$a = deep_ksort($a);
$b = deep_ksort($b);

echo "\n    Sorted serialize()\n";
echo md5(serialize($a))."\n";
echo md5(serialize($b))."\n";

echo "\n    Sorted json_encode()\n";
echo md5(json_encode($a))."\n";
echo md5(json_encode($b))."\n";

我的快速 deep_ksort() 实现适合这种情况,但在您自己的项目中使用之前请检查它:

/*
* Sort an array by keys, and additionally sort its array values by keys
*
* Does not try to sort an object, but does iterate its properties to
* sort arrays in properties
*/
function deep_ksort($input)
{
    if ( !is_object($input) && !is_array($input) ) {
        return $input;
    }

    foreach ( $input as $k=>$v ) {
        if ( is_object($v) || is_array($v) ) {
            $input[$k] = deep_ksort($v);
        }
    }

    if ( is_array($input) ) {
        ksort($input);
    }

    // Do not sort objects

    return $input;
}

I'm joining a very crowded party by answering, but there is an important consideration that none of the extant answers address. The value of json_encode() and serialize() both depend upon the order of elements in the array!

Here are the results of not sorting and sorting the arrays, on two arrays with identical values but added in a different order (code at bottom of post):

    serialize()
1c4f1064ab79e4722f41ab5a8141b210
1ad0f2c7e690c8e3cd5c34f7c9b8573a

    json_encode()
db7178ba34f9271bfca3a05c5dddf502
c9661c0852c2bd0e26ef7951b4ca9e6f

    Sorted serialize()
1c4f1064ab79e4722f41ab5a8141b210
1c4f1064ab79e4722f41ab5a8141b210

    Sorted json_encode()
db7178ba34f9271bfca3a05c5dddf502
db7178ba34f9271bfca3a05c5dddf502

Therefore, the two methods that I would recommend to hash an array would be:

// You will need to write your own deep_ksort(), or see
// my example below

md5(   serialize(deep_ksort($array)) );

md5( json_encode(deep_ksort($array)) );

The choice of json_encode() or serialize() should be determined by testing on the type of data that you are using. By my own testing on purely textual and numerical data, if the code is not running a tight loop thousands of times then the difference is not even worth benchmarking. I personally use json_encode() for that type of data.

Here is the code used to generate the sorting test above:

$a = array();
$a['aa'] = array( 'aaa'=>'AAA', 'bbb'=>'ooo', 'qqq'=>'fff',);
$a['bb'] = array( 'aaa'=>'BBBB', 'iii'=>'dd',);

$b = array();
$b['aa'] = array( 'aaa'=>'AAA', 'qqq'=>'fff', 'bbb'=>'ooo',);
$b['bb'] = array( 'iii'=>'dd', 'aaa'=>'BBBB',);

echo "    serialize()\n";
echo md5(serialize($a))."\n";
echo md5(serialize($b))."\n";

echo "\n    json_encode()\n";
echo md5(json_encode($a))."\n";
echo md5(json_encode($b))."\n";



$a = deep_ksort($a);
$b = deep_ksort($b);

echo "\n    Sorted serialize()\n";
echo md5(serialize($a))."\n";
echo md5(serialize($b))."\n";

echo "\n    Sorted json_encode()\n";
echo md5(json_encode($a))."\n";
echo md5(json_encode($b))."\n";

My quick deep_ksort() implementation, fits this case but check it before using on your own projects:

/*
* Sort an array by keys, and additionally sort its array values by keys
*
* Does not try to sort an object, but does iterate its properties to
* sort arrays in properties
*/
function deep_ksort($input)
{
    if ( !is_object($input) && !is_array($input) ) {
        return $input;
    }

    foreach ( $input as $k=>$v ) {
        if ( is_object($v) || is_array($v) ) {
            $input[$k] = deep_ksort($v);
        }
    }

    if ( is_array($input) ) {
        ksort($input);
    }

    // Do not sort objects

    return $input;
}
您的好友蓝忘机已上羡 2024-08-28 06:35:09

答案很大程度上取决于数组值的数据类型。
对于大字符串使用:

md5(serialize($array));

对于短字符串和整数使用:

md5(json_encode($array));

4 个内置 PHP 函数可以将数组转换为字符串:
序列化()json_encode()var_export()print_r()

注意: json_encode() 函数在处理以字符串作为值的关联数组时速度会变慢。在这种情况下,请考虑使用 serialize() 函数。

键和值中包含 md5 哈希(32 个字符)的多维数组的测试结果:

Test name       Repeats         Result          Performance     
serialize       10000           0.761195 sec    +0.00%
print_r         10000           1.669689 sec    -119.35%
json_encode     10000           1.712214 sec    -124.94%
var_export      10000           1.735023 sec    -127.93%

数字多维数组的测试结果:

Test name       Repeats         Result          Performance     
json_encode     10000           1.040612 sec    +0.00%
var_export      10000           1.753170 sec    -68.47%
serialize       10000           1.947791 sec    -87.18%
print_r         10000           9.084989 sec    -773.04%

关联数组 测试源
数字数组测试源

Answer is highly depends on data types of array values.
For big strings use:

md5(serialize($array));

For short strings and integers use:

md5(json_encode($array));

4 built-in PHP functions can transform array to string:
serialize(), json_encode(), var_export(), print_r().

Notice: json_encode() function slows down while processing associative arrays with strings as values. In this case consider to use serialize() function.

Test results for multi-dimensional array with md5-hashes (32 char) in keys and values:

Test name       Repeats         Result          Performance     
serialize       10000           0.761195 sec    +0.00%
print_r         10000           1.669689 sec    -119.35%
json_encode     10000           1.712214 sec    -124.94%
var_export      10000           1.735023 sec    -127.93%

Test result for numeric multi-dimensional array:

Test name       Repeats         Result          Performance     
json_encode     10000           1.040612 sec    +0.00%
var_export      10000           1.753170 sec    -68.47%
serialize       10000           1.947791 sec    -87.18%
print_r         10000           9.084989 sec    -773.04%

Associative array test source.
Numeric array test source.

橘香 2024-08-28 06:35:09

除了布罗克的出色答案(+1)之外,任何像样的散列库都允许您以增量方式更新散列,因此您应该能够顺序更新每个字符串,而不必构建一个巨大的字符串。

请参阅:hash_update

Aside from Brock's excellent answer (+1), any decent hashing library allows you to update the hash in increments, so you should be able to update with each string sequentially, instead having to build up one giant string.

See: hash_update

戏蝶舞 2024-08-28 06:35:09
md5(serialize($array));

可以工作,但是哈希值会根据数组的顺序而改变(但这可能并不重要)。

md5(serialize($array));

Will work, but the hash will change depending on the order of the array (that might not matter though).

零度℉ 2024-08-28 06:35:09

请注意,对于键不从 0 开始的数字数组或关联数组,serializejson_encode 的行为有所不同。
json_encode 会将此类数组存储为 Object,因此 json_decode 返回一个 Object,其中 unserialize 将返回一个具有完全相同键的数组。

Note that serialize and json_encode act differently when it comes to numeric arrays where the keys don't start at 0, or associative arrays.
json_encode will store such arrays as an Object, so json_decode returns an Object, where unserialize will return an array with exact the same keys.

想挽留 2024-08-28 06:35:09

我认为这可能是一个很好的提示:

Class hasharray {

    public function array_flat($in,$keys=array(),$out=array()){
        foreach($in as $k => $v){
            $keys[] = $k; 
            if(is_array($v)){
                $out = $this->array_flat($v,$keys,$out);
            }else{
                $out[implode("/",$keys)] = $v;
            }
            array_pop($keys);
        }
        return $out;  
    }

    public function array_hash($in){
        $a = $this->array_flat($in);
        ksort($a);
        return md5(json_encode($a));
    }

}

$h = new hasharray;
echo $h->array_hash($multi_dimensional_array);

I think that this could be a good tip:

Class hasharray {

    public function array_flat($in,$keys=array(),$out=array()){
        foreach($in as $k => $v){
            $keys[] = $k; 
            if(is_array($v)){
                $out = $this->array_flat($v,$keys,$out);
            }else{
                $out[implode("/",$keys)] = $v;
            }
            array_pop($keys);
        }
        return $out;  
    }

    public function array_hash($in){
        $a = $this->array_flat($in);
        ksort($a);
        return md5(json_encode($a));
    }

}

$h = new hasharray;
echo $h->array_hash($multi_dimensional_array);
无尽的现实 2024-08-28 06:35:09

我在上面没有那么容易地看到解决方案,所以我想提供一个更简单的答案。对我来说,在使用 ksort(键排序)之前我得到的是相同的键:

首先使用 Ksort 进行排序,然后对 json_encode 执行 sha1:

ksort($array)
$hash = sha1(json_encode($array) //be mindful of UTF8

示例:

$arr1 = array( 'dealer' => '100', 'direction' => 'ASC', 'dist' => '500', 'limit' => '1', 'zip' => '10601');
ksort($arr1);

$arr2 = array( 'direction' => 'ASC', 'limit' => '1', 'zip' => '10601', 'dealer' => '100', 'dist' => '5000');
ksort($arr2);

var_dump(sha1(json_encode($arr1)));
var_dump(sha1(json_encode($arr2)));

更改后的数组和哈希的输出:

string(40) "502c2cbfbe62e47eb0fe96306ecb2e6c7e6d014c"
string(40) "b3319c58edadab3513832ceeb5d68bfce2fb3983"

I didn't see the solution so easily above so I wanted to contribute a simpler answer. For me, I was getting the same key until I used ksort (key sort):

Sorted first with Ksort, then performed sha1 on a json_encode:

ksort($array)
$hash = sha1(json_encode($array) //be mindful of UTF8

example:

$arr1 = array( 'dealer' => '100', 'direction' => 'ASC', 'dist' => '500', 'limit' => '1', 'zip' => '10601');
ksort($arr1);

$arr2 = array( 'direction' => 'ASC', 'limit' => '1', 'zip' => '10601', 'dealer' => '100', 'dist' => '5000');
ksort($arr2);

var_dump(sha1(json_encode($arr1)));
var_dump(sha1(json_encode($arr2)));

Output of altered arrays and hashes:

string(40) "502c2cbfbe62e47eb0fe96306ecb2e6c7e6d014c"
string(40) "b3319c58edadab3513832ceeb5d68bfce2fb3983"
成熟稳重的好男人 2024-08-28 06:35:09

关于 serialize() 的重要说明

我不建议将其用作哈希函数的一部分,因为它可能会为以下示例返回不同的结果。检查下面的示例:

简单示例:

$a = new \stdClass;
$a->test = 'sample';

$b = new \stdClass;
$b->one = $a;
$b->two = clone $a;

Produces

"O:8:"stdClass":2:{s:3:"one";O:8:"stdClass":1:{s:4:"test";s:6:"sample";}s:3:"two";O:8:"stdClass":1:{s:4:"test";s:6:"sample";}}"

但以下代码:

<?php

$a = new \stdClass;
$a->test = 'sample';

$b = new \stdClass;
$b->one = $a;
$b->two = $a;

输出:

"O:8:"stdClass":2:{s:3:"one";O:8:"stdClass":1:{s:4:"test";s:6:"sample";}s:3:"two";r:2;}"

因此,php 只需创建链接“r:2;”,而不是第二个对象到第一个实例。这绝对是序列化数据的好且正确的方法,但它可能会导致散列函数出现问题。

Important note about serialize()

I don't recommend to use it as part of hashing function because it can return different result for the following examples. Check the example below:

Simple example:

$a = new \stdClass;
$a->test = 'sample';

$b = new \stdClass;
$b->one = $a;
$b->two = clone $a;

Produces

"O:8:"stdClass":2:{s:3:"one";O:8:"stdClass":1:{s:4:"test";s:6:"sample";}s:3:"two";O:8:"stdClass":1:{s:4:"test";s:6:"sample";}}"

But the following code:

<?php

$a = new \stdClass;
$a->test = 'sample';

$b = new \stdClass;
$b->one = $a;
$b->two = $a;

Output:

"O:8:"stdClass":2:{s:3:"one";O:8:"stdClass":1:{s:4:"test";s:6:"sample";}s:3:"two";r:2;}"

So instead of second object php just create link "r:2;" to the first instance. It's definitely good and correct way to serialize data, but it can lead to the issues with your hashing function.

白首有我共你 2024-08-28 06:35:09
// Convert nested arrays to a simple array
$array = array();
array_walk_recursive($input, function ($a) use (&$array) {
    $array[] = $a;
});

sort($array);

$hash = md5(json_encode($array));

----

These arrays have the same hash:
$arr1 = array(0 => array(1, 2, 3), 1, 2);
$arr2 = array(0 => array(1, 3, 2), 1, 2);
// Convert nested arrays to a simple array
$array = array();
array_walk_recursive($input, function ($a) use (&$array) {
    $array[] = $a;
});

sort($array);

$hash = md5(json_encode($array));

----

These arrays have the same hash:
$arr1 = array(0 => array(1, 2, 3), 1, 2);
$arr2 = array(0 => array(1, 3, 2), 1, 2);
百善笑为先 2024-08-28 06:35:09

有几个答案告诉使用 json_code,

但是 json_encode 不能很好地处理 iso-8859-1 字符串,一旦有特殊字符,字符串就会被裁剪。

我建议使用 var_export :

md5(var_export($array, true))

不像序列化那么慢,不像 json_encode 那么有问题

there are several answers telling to use json_code,

but json_encode don't work fine with iso-8859-1 string, as soon as there is a special char, the string is cropped.

i would advice to use var_export :

md5(var_export($array, true))

not as slow as serialize, not as bugged as json_encode

幻想少年梦 2024-08-28 06:35:09

当前得票最高的答案md5(serialize($array));不适用于对象。

考虑代码:

 $a = array(new \stdClass());
 $b = array(new \stdClass());

即使数组不同(它们包含不同的数组)对象),使用 md5(serialize($array)); 时它们具有相同的哈希值。所以你的哈希值没用!

为了避免这个问题,您可以在序列化之前用 spl_object_hash() 的结果替换对象。如果您的数组有多个级别,您还应该递归地执行此操作。

正如 dotancohen 所建议的,下面的代码还按键对数组进行排序。

function replaceObjectsWithHashes(array $array)
{
    foreach ($array as &$value) {
        if (is_array($value)) {
            $value = $this->replaceObjectsInArrayWithHashes($value);
        } elseif (is_object($value)) {
            $value = spl_object_hash($value);
        }
    }
    ksort($array);
    return $array;
}

现在您可以使用md5(serialize(replaceObjectsWithHashes($array)))

(请注意,PHP 中的数组是值类型。因此 replaceObjectsWithHashes 函数不会更改原始数组。)

Currently the most up-voted answer md5(serialize($array)); doesn't work well with objects.

Consider code:

 $a = array(new \stdClass());
 $b = array(new \stdClass());

Even though arrays are different (they contain different objects), they have same hash when using md5(serialize($array));. So your hash is useless!

To avoid that problem, you can replace objects with result of spl_object_hash() before serializing. You also should do it recursively if your array has multiple levels.

Code below also sorts arrays by keys, as dotancohen have suggested.

function replaceObjectsWithHashes(array $array)
{
    foreach ($array as &$value) {
        if (is_array($value)) {
            $value = $this->replaceObjectsInArrayWithHashes($value);
        } elseif (is_object($value)) {
            $value = spl_object_hash($value);
        }
    }
    ksort($array);
    return $array;
}

Now you can use md5(serialize(replaceObjectsWithHashes($array))).

(Note that the array in PHP is value type. So replaceObjectsWithHashes function DO NOT change original array.)

许仙没带伞 2024-08-28 06:35:09

在某些情况下,也许最好使用 http_build_query 将数组转换为字符串:

md5( http_build_query( $array ) );

in some case maybe it's better to use http_build_query to convert array to string :

md5( http_build_query( $array ) );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文