Skip to content

Commit 85df4db

Browse files
aran112000otsch
authored andcommitted
Normalise query strings with duplicate keys to array notation
1 parent af52c17 commit 85df4db

File tree

1 file changed

+29
-0
lines changed

1 file changed

+29
-0
lines changed

src/Query.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,8 @@ private function sanitize(string $query): string
555555
}
556556

557557
$query = preg_replace('/&+/', '&', $query) ?? $query;
558+
559+
$query = $this->normalizeArrays($query);
558560

559561
return $this->arrayToString($this->stringToArray($query));
560562
}
@@ -1000,4 +1002,31 @@ private function spaceCharacter(): string
10001002

10011003
return '%20';
10021004
}
1005+
1006+
/**
1007+
* Arrays can be present in query strings in two formats, as follows:
1008+
* 1.) ?key[]=value1&key[]=value2
1009+
* 2.) ?key=value1&key=value2
1010+
*
1011+
* Both *should* be parsed in the same way, however, PHP's parse_str() doesn't handle version #1. This function
1012+
* normalizes version #2 structure query strings to #1 so that we can parse both accordingly.
1013+
*/
1014+
private function normalizeArrays(string $query): string
1015+
{
1016+
// Count the occurrences of all request keys to check for duplicates
1017+
$keyOccurrences = array_count_values(array_map(fn ($val) => explode('=', $val, 2)[0], explode('&', $query)));
1018+
1019+
foreach ($keyOccurrences as $key => $count) {
1020+
if ($count > 1 && !strstr($key, '[')) {
1021+
// Duplicate query string key without array notation, convert to {keyName}[] structure
1022+
$query = preg_replace(
1023+
'#(^|[?&])(' . preg_quote($key) . ')=#',
1024+
'$1$2[]=',
1025+
$query,
1026+
);
1027+
}
1028+
}
1029+
1030+
return $query;
1031+
}
10031032
}

0 commit comments

Comments
 (0)