【问题标题】:Apache rewrite query string (checkbox array)Apache 重写查询字符串(复选框数组)
【发布时间】:2011-05-25 00:51:02
【问题描述】:

如何重写查询字符串,如:

test.php?cat1[]=18&cat1[]=687&xxx[]=5&xxx[]=3&xxx[]=1&yyy[]=6

test.php?cat1=18,687,5&xxx=3,1&yyy=6

请注意,参数(名称和值对)是动态生成的。

【问题讨论】:

  • 绝对有可能。但我不会用 mod_rewrite 而是用 PHP。

标签: php wordpress mod-rewrite url-rewriting


【解决方案1】:
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))));
}

【讨论】:

  • 考虑'/[\][]/',如果你改变它,只分配给$_GET[$key];您甚至可以拥有foreach ($_GET as $key => &$val) 并直接分配给$val,因此不会复制该数组。否则,干得好 (+1)。
  • @PointedEars: 好点,tnx ;-) 我还添加了一些东西来剥离空 val 以防万一。 ;-)
【解决方案2】:

我找到了一种无需修改代码即可进行此转换的解决方案。

在 httpd.conf(在我的 VirtualHost 部分中)我定义了一个重写映射:

RewriteMap programmap prg:/var/www/localhost/htdocs/chg.php

然后在 .htaccess 中我设置了以下规则:

RewriteEngine On

RewriteCond %{QUERY_STRING} (.*)
RewriteRule ^(script.php) $1?${programmap:%1} [L]

$1 代表 RewriteRule 中的第一个“()”

%1 代表 RewriteCond 中的第一个“()”

然后我编写这个脚本“/var/www/localhost/htdocs/chg.php”(用 PHP 但可以用 C、Perl 或其他语言):

#!/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";
}

【讨论】:

    【解决方案3】:

    test.php?cat1=18,687,5&xxx=3,1&yyy=6

    尝试在您的代码之前插入此函数:

    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);
    

    将打印

    array(3) { ["cat1"]=> array(3) { [0]=> string(2) "18" [1]=> string(3) "687" [2]=> 字符串(1) "5" } ["xxx"]=> 数组(2) { [0]=> 字符串(1) "3" [1]=> 字符串(1) "1" } ["yyy"]=> 字符串(1) "6" }

    【讨论】:

      【解决方案4】:

      这是一个简短的 php 脚本,用于创建您想要的查询字符串。最好不要使用 mod_rewrite 来完成这部分,因为它完全超出了该范围:

      <?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);
      
      ?>
      

      例如,如果将该脚本保存为 /rewrite.php,则可以在 .htaccess 文件中包含这些规则,以将带有包含数组的查询字符串的请求重新路由到 /rewrite.php

      RewriteCond %{QUERY_STRING} \[\]
      RewriteRule ^test.php /rewrite.php [L,QSA]
      

      然后rewrite.php 脚本将重写查询字符串并使用连接的查询字符串重定向浏览器。

      【讨论】:

      • 在我的上下文中,我使用的是 WordPress,而您示例中的“test.php”是一个名为“advanced-search”的页面(这是一个已由 .htaccess 重写的漂亮永久链接)位于@“root/wordpress/advanced-search”;查询显示如下:“root/wordpress/advanced-search...;我需要对您的脚本进行任何调整以使其正常工作吗?谢谢!
      • 查询是什么样的?该链接在 /advanced-search/ 之后没有任何内容。您可能希望将重写更改为 /wordpress/advanced-search/ 到 /rewrite.php(或任何您想命名的名称),然后在 rewrite.php 的底部,使用 pring(get_file_contents("http://your-host/wordpress/advanced-search?$ret")); 而不是重定向浏览器header()
      • 查询看起来像:10.0.1.4:8888[slash]wordpress[slash]advanced-search[slash]?property_type[]=loft&property_type[]=residential
      • 所以不要将漂亮的 premalink URL 重写为 /wordpress/advanced-search,而是写入 /rewrite.php(或您命名该脚本的任何名称),而不是使用 2 个标题行来重定向浏览器,使用我的在我之前的评论中建议加载页面并输出结果。
      • 所以表单 HTML 应该如下所示:
        ?
      猜你喜欢
      • 1970-01-01
      • 2019-02-13
      • 2016-08-13
      • 2016-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-27
      相关资源
      最近更新 更多