【问题标题】:How to combine query strings in PHP如何在 PHP 中组合查询字符串
【发布时间】:2011-03-01 10:49:42
【问题描述】:

给定一个 url 和一个查询字符串,我怎样才能得到查询字符串和 url 组合产生的 url?

我正在寻找类似于 .htaccess 的qsa 的功能。我意识到完全手动实现这将是相当微不足道的,但是是否有处理查询字符串的内置函数可以简化或完全解决这个问题?

示例输入/结果集:

Url="http://www.example.com/index.php/page?a=1"
QS ="?b=2"
Result="http://www.example.com/index.php/page?a=1&b=2"

-

Url="page.php"
QS ="?b=2"
Result="page.php?b=2"

【问题讨论】:

  • 您是从 example.com 网站管理员的角度来看,还是从用户(“黑客”)的角度来看?

标签: php query-string qsa


【解决方案1】:

不使用 PECL 扩展并且不是大量复制和粘贴函数的东西怎么样?它仍然有点复杂,因为您正在将两个查询字符串拼接在一起,并且想要以不只是 $old .= $new;

的方式进行操作

我们将使用 parse_url 从所需的 url 中提取查询字符串,parse_str 解析您希望加入的查询字符串,array_merge 将它们连接在一起,并使用 http_build_query 创建新的,为我们组合字符串。

// Parse the URL into components
$url = 'http://...';
$url_parsed = parse_url($url);
$new_qs_parsed = array();
// Grab our first query string
parse_str($url_parsed['query'], $new_qs_parsed);
// Here's the other query string
$other_query_string = 'that=this&those=these';
$other_qs_parsed = array();
parse_str($other_query_string, $other_qs_parsed);
// Stitch the two query strings together
$final_query_string_array = array_merge($new_qs_parsed, $other_qs_parsed);
$final_query_string = http_build_query($final_query_string_array);
// Now, our final URL:
$new_url = $url_parsed['scheme'] 
         . '://'
         . $url_parsed['host'] 
         . $url_parsed['path'] 
         . '?'      
         . $final_query_string;

【讨论】:

  • +1 奇迹般地成为唯一一个愿意使用适当的、随时可用的功能的人。这可能是我的一个小烦恼,但是所有这些人重新重新重新发明已经可用的功能是 PHP 获得不好名声的重要原因。
  • @Wrikken 我实际上更喜欢重新发明轮子,当涉及到http_build_query 和查询字符串解析时。处理同一查询参数的多个值的方式与 PHP 之外的所有其他内容(例如 Java 的 ServletRequest.getParameterValues)不兼容。
  • 这不太正确,因为查询字符串可能多次具有不同值的相同值,有时保留参数顺序很重要。
  • 不幸的是,正确保留参数顺序(而不是自动转换为 [] 语法)的代码会大得多,与轮子改造一样。然而,这是有道理的。
  • 将此切换为最佳答案(用于选择 wordpress 之一)。这个更简洁并使用内置函数(就像我在问题中提出的那样)。
【解决方案2】:

那么,如果 url 发生冲突怎么办?如果两个 url 在查询字符串中都包含 b= 组件?你需要决定哪个占主导地位。

这里有一段代码可以做你想做的事,将每个字符串解析为一个 url,然后提取 query url 部分和 implode() 将它们重新组合在一起。

$url="http://www.example.com/index.php/page?a=1";
$qs ="?b=2";

$url_parsed = parse_url($url);
$qs_parsed = parse_url($qs);

$args = array(
    $url_parsed['query'],
    $qs_parsed['query'],
);

$new_url = $url_parsed['scheme'];
$new_url .= '://';
$new_url .= $url_parsed['host'];
$new_url .= $url_parsed['path'];
$new_url .= '?';
$new_url .= implode('&', $args);

print $new_url;

【讨论】:

    【解决方案3】:

    您可以使用以下方法从 url 获取查询字符串部分:

    $_SERVER['QUERY_STRING']
    

    然后正常附加到url。

    如果您想在查询字符串中指定自己的自定义变量,请查看:

    http_build_query

    【讨论】:

      【解决方案4】:

      没有内置函数可以做到这一点。但是,您可以从 http PECL 扩展中使用此功能,

      http://usphp.com/manual/en/function.http-build-url.php

      例如,

      $url = http_build_url("http://www.example.com/index.php/page?a=1",
          array(
              "b" => "2"
          )
      );
      

      【讨论】:

        【解决方案5】:

        这是从 WordPress“框架”中提取的一系列功能,可以做到这一点,但这可能太多了:

        add_query_arg()

        /**
         * Retrieve a modified URL query string.
         *
         * You can rebuild the URL and append a new query variable to the URL query by
         * using this function. You can also retrieve the full URL with query data.
         *
         * Adding a single key & value or an associative array. Setting a key value to
         * emptystring removes the key. Omitting oldquery_or_uri uses the $_SERVER
         * value.
         *
         * @since 1.0
         *
         * @param mixed $param1 Either newkey or an associative_array
         * @param mixed $param2 Either newvalue or oldquery or uri
         * @param mixed $param3 Optional. Old query or uri
         * @return string New URL query string.
         */
        public function add_query_arg() {
            $ret = '';
            if ( is_array( func_get_arg(0) ) ) {
                $uri = ( @func_num_args() < 2 || false === @func_get_arg( 1 ) ) ? $_SERVER['REQUEST_URI'] : @func_get_arg( 1 );
            } else {
                $uri = ( @func_num_args() < 3 || false === @func_get_arg( 2 ) ) ? $_SERVER['REQUEST_URI'] : @func_get_arg( 2 );
            }
        
            if ( $frag = strstr( $uri, '#' ) ) {
                $uri = substr( $uri, 0, -strlen( $frag ) );
            } else {
                $frag = '';
            }
        
            if ( preg_match( '|^https?://|i', $uri, $matches ) ) {
                $protocol = $matches[0];
                $uri = substr( $uri, strlen( $protocol ) );
            } else {
                $protocol = '';
            }
        
            if ( strpos( $uri, '?' ) !== false ) {
                $parts = explode( '?', $uri, 2 );
                if ( 1 == count( $parts ) ) {
                    $base = '?';
                    $query = $parts[0];
                } else {
                    $base = $parts[0] . '?';
                    $query = $parts[1];
                }
            } elseif ( !empty( $protocol ) || strpos( $uri, '=' ) === false ) {
                $base = $uri . '?';
                $query = '';
            } else {
                $base = '';
                $query = $uri;
            }
        
            parse_str( $query, $qs );
        
            if ( get_magic_quotes_gpc() )
                $qs = format::stripslashes_deep( $qs );
        
            $qs = format::urlencode_deep( $qs ); // this re-URL-encodes things that were already in the query string
            if ( is_array( func_get_arg( 0 ) ) ) {
                $kayvees = func_get_arg( 0 );
                $qs = array_merge( $qs, $kayvees );
            } else {
                $qs[func_get_arg( 0 )] = func_get_arg( 1 );
            }
        
            foreach ( ( array ) $qs as $k => $v ) {
                if ( $v === false )
                    unset( $qs[$k] );
            }
        
            $ret = http_build_query( $qs, '', '&' );
            $ret = trim( $ret, '?' );
            $ret = preg_replace( '#=(&|$)#', '$1', $ret );
            $ret = $protocol . $base . $ret . $frag;
            $ret = rtrim( $ret, '?' );
            return $ret;
        }
        

        stripslashes_deep()

        /**
         * Navigates through an array and removes slashes from the values.
         *
         * If an array is passed, the array_map() function causes a callback to pass the
         * value back to the function. The slashes from this value will removed.
         *
         * @since 1.0
         *
         * @param array|string $value The array or string to be stripped
         * @return array|string Stripped array (or string in the callback).
         */
        function stripslashes_deep( $value ) {
            return is_array( $value ) ? array_map( array('self', 'stripslashes_deep'), $value ) : stripslashes( $value );
        }
        

        urlencode_deep()

        /**
         * Navigates through an array and encodes the values to be used in a URL.
         *
         * Uses a callback to pass the value of the array back to the function as a
         * string.
         *
         * @since 1.0
         *
         * @param array|string $value The array or string to be encoded.
         * @return array|string $value The encoded array (or string from the callback).
         */
        public function urlencode_deep( $value ) {
            return is_array($value) ? array_map( array('self', 'urlencode_deep'), $value) : urlencode($value);
        }
        

        【讨论】:

        • 这实际上是完美的;我在网站上设置了一个 wp 博客,所以该功能已经存在。谢谢!
        猜你喜欢
        • 2022-08-21
        • 1970-01-01
        • 2011-02-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-15
        相关资源
        最近更新 更多