Immutable hash for arrays, add not sort keys flag

This commit is contained in:
2026-09-18 21:53:36 +09:00
parent 3a33f07ae7
commit 369f2e2586
3 changed files with 42 additions and 7 deletions
+34 -5
View File
@@ -434,26 +434,47 @@ final class CoreLibsCreateHashTest extends TestCase
return [ return [
'Empty array' => [ 'Empty array' => [
[], [],
null,
'064f01fe', '064f01fe',
], ],
'Simple array' => [ 'Simple array' => [
['key' => 'value'], ['key' => 'value'],
null,
'78f40899', '78f40899',
], ],
'flat array a' => [ 'flat array a' => [
[0, 1, 'b', 'c', 'a'], [0, 1, 'b', 'c', 'a'],
null,
'ccec0f5b', 'ccec0f5b',
], ],
'flat array b' => [ 'flat array b' => [
['b', 'c', 'a', 1, 0], ['b', 'c', 'a', 1, 0],
null,
'c6040f5b',
],
'flat array b, not sorted' => [
['b', 'c', 'a', 1, 0],
false,
'c6040f5b', 'c6040f5b',
], ],
'key array a' => [ 'key array a' => [
['A' => 0, 'F' => 1, 'C' => 'b', 'K' => 'c', 'B' => 'a'], ['A' => 0, 'F' => 1, 'C' => 'b', 'K' => 'c', 'B' => 'a'],
null,
'01f11355', '01f11355',
], ],
'key array a, not sorted' => [
['A' => 0, 'F' => 1, 'C' => 'b', 'K' => 'c', 'B' => 'a'],
false,
'04911355',
],
'key array b' => [ 'key array b' => [
['A' => 0, 'B' => 'a', 'C' => 'b', 'F' => 1, 'K' => 'c'], ['A' => 0, 'B' => 'a', 'C' => 'b', 'F' => 1, 'K' => 'c'],
null,
'01f11355',
],
'key array b, not sorted' => [
['A' => 0, 'B' => 'a', 'C' => 'b', 'F' => 1, 'K' => 'c'],
false,
'01f11355', '01f11355',
], ],
'complex nested array' => [ 'complex nested array' => [
@@ -464,6 +485,7 @@ final class CoreLibsCreateHashTest extends TestCase
] ]
] ]
], ],
null,
'd8de1565', 'd8de1565',
] ]
]; ];
@@ -479,12 +501,19 @@ final class CoreLibsCreateHashTest extends TestCase
* @param array<mixed> $input * @param array<mixed> $input
* @param string $expected * @param string $expected
*/ */
public function testGenerateImmutableHashForArray(array $input, string $expected): void public function testGenerateImmutableHashForArray(array $input, ?bool $sort_keys, string $expected): void
{ {
$this->assertEquals( if ($sort_keys === null) {
$expected, $this->assertEquals(
\CoreLibs\Create\Hash::generateImmutableHashForArray($input) $expected,
); \CoreLibs\Create\Hash::generateImmutableHashForArray($input)
);
} else {
$this->assertEquals(
$expected,
\CoreLibs\Create\Hash::generateImmutableHashForArray($input, $sort_keys)
);
}
} }
} }
+1
View File
@@ -113,6 +113,7 @@ $tests = [
]; ];
foreach ($tests as $test) { foreach ($tests as $test) {
print "IMMUTABLE HASH FOR ARRAY: " . Hash::generateImmutableHashForArray($test) . "<br>"; print "IMMUTABLE HASH FOR ARRAY: " . Hash::generateImmutableHashForArray($test) . "<br>";
print "IMMUTABLE HASH FOR ARRAY: " . Hash::generateImmutableHashForArray($test, sort_keys:false) . "<br>";
print "SERIALIZED HASH FOR ARRAY: " . hash(Hash::DEFAULT_HASH, serialize($test)) . "<br>"; print "SERIALIZED HASH FOR ARRAY: " . hash(Hash::DEFAULT_HASH, serialize($test)) . "<br>";
} }
+7 -2
View File
@@ -215,17 +215,22 @@ class Hash
/** /**
* generate a hash over any array data * generate a hash over any array data
* optional will not sort keys and so create hashes based on the original data.
* for correct array comapre it is recommended to keep sort keys on
* *
* @param array<mixed> $data * @param array<mixed> $data
* @param bool $sort_keys [true] Whether to sort the array keys before hashing
* @return string * @return string
*/ */
public static function generateImmutableHashForArray(array $data): string public static function generateImmutableHashForArray(array $data, bool $sort_keys = true): string
{ {
// Create a sorted copy to ensure consistent hashing // Create a sorted copy to ensure consistent hashing
// Generate hash using serialize for better accuracy // Generate hash using serialize for better accuracy
return hash( return hash(
self::DEFAULT_HASH, self::DEFAULT_HASH,
serialize(ArrayHandler::createSortedArrayByKey($data)) serialize(
$sort_keys ? ArrayHandler::createSortedArrayByKey($data) : $data
)
); );
} }
} }