PHP MD5多维数组最好的方法?
生成多维数组的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
(底部可复制粘贴功能)
如前所述,以下内容将起作用。
然而,值得注意的是(具有讽刺意味的是)json_encode 的执行速度明显更快:
事实上,速度增加了两倍,因为 (1) json_encode 单独的执行速度比序列化更快,并且 (2) json_encode 生成字符串较小,因此 md5 需要处理的内容较少。
编辑:以下是支持这一说法的证据:
JSON_ENCODE 始终快 250% (2.5 倍) 以上(通常超过 300%)——这不是一个微不足道的差异。您可以在此处查看使用此实时脚本的测试结果:
现在,需要注意的一件事是 array(1,2,3) 将生成与 array(3,2,1) 不同的 MD5。 如果这不是您想要的。尝试以下代码:
编辑: 有人质疑颠倒顺序是否会产生相同的结果。所以,我在这里(正确)做到了:
正如你所看到的,结果是完全一样的。这是(更正)测试最初由 Drupal 相关人员创建:
为了更好地衡量,这里有一个函数/方法,您可以复制粘贴(在5.3.3-1ubuntu9.5中测试):
(Copy-n-paste-able function at the bottom)
As mentioned prior, the following will work.
However, it's worth noting that (ironically) json_encode performs noticeably faster:
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:
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:
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):
我通过回答加入了一个非常拥挤的聚会,但有一个重要的考虑因素,现有的答案都没有解决。
json_encode()
和serialize()
的值都取决于数组中元素的顺序!下面是不排序和排序的结果对两个具有相同值但以不同顺序添加的数组对数组进行排序(帖子底部的代码):
因此,我推荐给的两种方法 >哈希数组将是:
json_encode()
或serialize()
的选择应该通过测试<的数据类型来确定em>您正在使用。通过我自己对纯文本和数字数据的测试,如果代码没有运行紧密循环数千次,那么差异甚至不值得进行基准测试。我个人使用 json_encode() 来处理该类型的数据。这是用于生成上述排序测试的代码:
我的快速 deep_ksort() 实现适合这种情况,但在您自己的项目中使用之前请检查它:
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()
andserialize()
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):
Therefore, the two methods that I would recommend to hash an array would be:
The choice of
json_encode()
orserialize()
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 usejson_encode()
for that type of data.Here is the code used to generate the sorting test above:
My quick deep_ksort() implementation, fits this case but check it before using on your own projects:
答案很大程度上取决于数组值的数据类型。
对于大字符串使用:
对于短字符串和整数使用:
4 个内置 PHP 函数可以将数组转换为字符串:
序列化()、json_encode()、var_export()、print_r()。
键和值中包含 md5 哈希(32 个字符)的多维数组的测试结果:
数字多维数组的测试结果:
关联数组 测试源。
数字数组测试源。
Answer is highly depends on data types of array values.
For big strings use:
For short strings and integers use:
4 built-in PHP functions can transform array to string:
serialize(), json_encode(), var_export(), print_r().
Test results for multi-dimensional array with md5-hashes (32 char) in keys and values:
Test result for numeric multi-dimensional array:
Associative array test source.
Numeric array test source.
除了布罗克的出色答案(+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
可以工作,但是哈希值会根据数组的顺序而改变(但这可能并不重要)。
Will work, but the hash will change depending on the order of the array (that might not matter though).
请注意,对于键不从 0 开始的数字数组或关联数组,
serialize
和json_encode
的行为有所不同。json_encode
会将此类数组存储为Object
,因此json_decode
返回一个Object
,其中unserialize 将返回一个具有完全相同键的数组。
Note that
serialize
andjson_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 anObject
, sojson_decode
returns anObject
, whereunserialize
will return an array with exact the same keys.我认为这可能是一个很好的提示:
I think that this could be a good tip:
我在上面没有那么容易地看到解决方案,所以我想提供一个更简单的答案。对我来说,在使用 ksort(键排序)之前我得到的是相同的键:
首先使用 Ksort 进行排序,然后对 json_encode 执行 sha1:
示例:
更改后的数组和哈希的输出:
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:
example:
Output of altered arrays and hashes:
关于
serialize()
的重要说明我不建议将其用作哈希函数的一部分,因为它可能会为以下示例返回不同的结果。检查下面的示例:
简单示例:
Produces
但以下代码:
输出:
因此,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:
Produces
But the following code:
Output:
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.
有几个答案告诉使用 json_code,
但是 json_encode 不能很好地处理 iso-8859-1 字符串,一旦有特殊字符,字符串就会被裁剪。
我建议使用 var_export :
不像序列化那么慢,不像 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 :
not as slow as serialize, not as bugged as json_encode
当前得票最高的答案
md5(serialize($array));
不适用于对象。考虑代码:
即使数组不同(它们包含不同的数组)对象),使用
md5(serialize($array));
时它们具有相同的哈希值。所以你的哈希值没用!为了避免这个问题,您可以在序列化之前用
spl_object_hash()
的结果替换对象。如果您的数组有多个级别,您还应该递归地执行此操作。正如 dotancohen 所建议的,下面的代码还按键对数组进行排序。
现在您可以使用
md5(serialize(replaceObjectsWithHashes($array)))
。(请注意,PHP 中的数组是值类型。因此
replaceObjectsWithHashes
函数不会更改原始数组。)Currently the most up-voted answer
md5(serialize($array));
doesn't work well with objects.Consider code:
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.
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.)在某些情况下,也许最好使用 http_build_query 将数组转换为字符串:
in some case maybe it's better to use http_build_query to convert array to string :