PHP best way to MD5 multi-dimensional array? PHP best way to MD5 multi-dimensional array? arrays arrays

PHP best way to MD5 multi-dimensional 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));}


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()1c4f1064ab79e4722f41ab5a8141b2101ad0f2c7e690c8e3cd5c34f7c9b8573a    json_encode()db7178ba34f9271bfca3a05c5dddf502c9661c0852c2bd0e26ef7951b4ca9e6f    Sorted serialize()1c4f1064ab79e4722f41ab5a8141b2101c4f1064ab79e4722f41ab5a8141b210    Sorted json_encode()db7178ba34f9271bfca3a05c5dddf502db7178ba34f9271bfca3a05c5dddf502

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 belowmd5(   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 additionall 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;}