If you need the key names preserved and don't want spaces or . or unmatched [ or ] replaced by an underscore, yet you want all the other goodies of parse_str(), like turning matched [] into array elements, you can use this code as a base for that.
<?php
const periodPlaceholder = 'QQleQPunT';
const spacePlaceholder = 'QQleQSpaTIE';
function parse_str_clean($querystr): array {
    $qquerystr = str_ireplace(['.','%2E','+',' ','%20'], [periodPlaceholder,periodPlaceholder,spacePlaceholder,spacePlaceholder,spacePlaceholder], $querystr);
    $arr = null ; parse_str($qquerystr, $arr);
    sanitizeKeys($arr, $querystr);
    return $arr;
}
function sanitizeKeys(&$arr, $querystr) {
    foreach($arr as $key=>$val) {
        $newval = $val ;
        if ( is_string($val)) {
            $newval = str_replace([periodPlaceholder,spacePlaceholder], ["."," "], $val);
        }
        $newkey = str_replace([periodPlaceholder,spacePlaceholder], ["."," "], $key);
        
        if ( str_contains($newkey, '_') ) { 
            $regex = '/&('.str_replace('_', '[ \.\[\]]', preg_quote($newkey, '/')).')=/';
            $matches = null ;
            if ( preg_match_all($regex, "&".urldecode($querystr), $matches) ) {
                if ( count(array_unique($matches[1])) === 1 && $key != $matches[1][0] ) {
                    $newkey = $matches[1][0] ;
                }
            }
        }
        if ( $newkey != $key ) {
            unset($arr[$key]);
            $arr[$newkey] = $newval ;
        } elseif( $val != $newval ) 
            $arr[$key] = $newval;
        if ( is_array($val)) {
            sanitizeKeys($arr[$newkey], $querystr);
        }
    }
}
?>
For example:
parse_str_clean("code.1=printr%28hahaha&code 1=448044&test.mijn%5B%5D%5B2%5D=test%20Roemer&test%5Bmijn=test%202e%20Roemer");
Produces:
array(4) {
  ["code.1"]=>
  string(13) "printr(hahaha"
  ["code 1"]=>
  string(6) "448044"
  ["test.mijn"]=>
  array(1) {
    [0]=>
    array(1) {
      [2]=>
      string(11) "test Roemer"
    }
  }
  ["test[mijn"]=>
  string(14) "test 2e Roemer"
}
Whereas if you feed the same querystring to parse_str, you will get
array(2) {
  ["code_1"]=>
  string(6) "448044"
  ["test_mijn"]=>
  string(14) "test 2e Roemer"
}