Reputation: 41
How is it possible to rewrite the query string like:
test.php?cat1[]=18&cat1[]=687&xxx[]=5&xxx[]=3&xxx[]=1&yyy[]=6
to
test.php?cat1=18,687,5&xxx=3,1&yyy=6
Note that the parameters (name and value pairs) are generated dynamically.
Upvotes: 4
Views: 1001
Reputation: 31173
if (preg_match('/[\][]/',$_SERVER['QUERY_STRING'])) {
foreach ($_GET as $key => &$val) {
$_GET[$key] = is_array($val) ? implode(',', $val) : $val;
}
header('Location: test.php?'.rawurldecode(http_build_query(array_filter($_GET))));
}
Upvotes: 3
Reputation: 4145
I found a solution to do this transformation without modifying the code.
In the httpd.conf (in my VirtualHost section) I define a rewrite map:
RewriteMap programmap prg:/var/www/localhost/htdocs/chg.php
Then in the .htaccess I set the following rules:
RewriteEngine On
RewriteCond %{QUERY_STRING} (.*)
RewriteRule ^(script.php) $1?${programmap:%1} [L]
$1 stand for first "()" in RewriteRule
%1 stand for first "()" in RewriteCond
Then I write this script "/var/www/localhost/htdocs/chg.php" (in PHP but can be in C, Perl, or whatelse):
#!/usr/bin/php -f
<?php
$pos1 = 2;
$pos2 = $pos1 + 1;
$reg = '/(([a-z0-9_]+)\[\]=([^&]*))/';
while(true){
$res=array();
$buff = trim(fgets(STDIN));
if(feof(STDIN)){
break;
}
$r = preg_match_all($reg, $buff, $match,PREG_SET_ORDER);
if($r){
foreach($match as $row){
if(!isset($res[$row[$pos1]])){
$res[$row[$pos1]] = $row[$pos1]."=".$row[$pos2];
} else {
$res[$row[$pos1]] .= ",".$row[$pos2];
}
}
$out=join('&',$res);
} else {
$out=$buff;
}
echo "$out\n";
}
Upvotes: 0
Reputation: 191
test.php?cat1=18,687,5&xxx=3,1&yyy=6
try to insert this function before your code:
url_parsestring2array(& $_GET);
function url_parsestring2array($args)
{
if (empty($args) || !is_array($args) || !$args) {
return;
}
foreach ($args as $key => $val) {
$tmp = explode(',', $val);
if (count($tmp) > 1) {
$args[$key] = $tmp;
}
}
}
var_dump($_GET);
will print
array(3) { ["cat1"]=> array(3) { [0]=> string(2) "18" [1]=> string(3) "687" [2]=> string(1) "5" } ["xxx"]=> array(2) { [0]=> string(1) "3" [1]=> string(1) "1" } ["yyy"]=> string(1) "6" }
Upvotes: 1
Reputation: 143886
Here's a short php script that creates the query string that you want. It's best not to do this part using mod_rewrite, because it's simply outside of that scope:
<?php
$ret = "";
foreach($_GET as $key=>$val) {
if(is_array($val)) {
// Create the comma separated string
$value = $val[0];
$length = count($val);
for($i=1; $i < $length; $i++) {
$value .= ',' . $val[$i];
}
$ret .= "$key=$value&";
} else {
$ret .= "$key=$val&";
}
}
// Remove last '&'
$ret = substr($ret , 0, strlen($ret)-1);
// Redirect the browser
header('HTTP/1.1 302 Moved');
header("Location: /test.php?" . $ret);
?>
If you save that script as /rewrite.php
, for example, then you can include these rules in the .htaccess file to reroute requests with query strings containing arrays to /rewrite.php
:
RewriteCond %{QUERY_STRING} \[\]
RewriteRule ^test.php /rewrite.php [L,QSA]
Then the rewrite.php script will rewrite the query string and redirect the browser with the concatenated query string.
Upvotes: 8