【问题标题】:Manipulate a url string by adding GET parameters通过添加 GET 参数来操作 url 字符串
【发布时间】:2011-08-14 03:57:35
【问题描述】:

我想在不重复 ?& 的情况下将 GET 参数添加到可能包含也可能不包含 GET 参数的 URL。

例子:

如果我想添加category=action

$url="http://www.acme.com";
 // will add ?category=action at the end

$url="http://www.acme.com/movies?sort=popular";
 // will add &category=action at the end

如果你注意到我试图不重复问号,如果它找到了。

URL 只是一个字符串。

附加特定 GET 参数的可靠方法是什么?

【问题讨论】:

  • 只需使用:echo http_build_url($url, array("query" => "the=query&parts=here"), HTTP_URL_JOIN_QUERY);。但是您需要pecl install pecl_http 或通过composer 安装jakeasmith/http_build_url

标签: php url string


【解决方案1】:
$parameters = array();

foreach ($get as $key => $value)
{
     $parameters[] = $key.'='.$value;
}

$url = 'http://example.com/movies?'.implode('&', $parameters);

【讨论】:

    【解决方案2】:

    使用strpos 来检测?。自从 ?只能出现在查询字符串开头的 URL 中,你知道它的参数是否已经存在,你需要使用 & 来添加参数

    function addGetParamToUrl(&$url, $varName, $value)
    {
        // is there already an ?
        if (strpos($url, "?"))
        {
            $url .= "&" . $varName . "=" . $value; 
        }
        else
        {
            $url .= "?" . $varName . "=" . $value;
        }
    }
    

    【讨论】:

    • 如果您关心性能,这是一种很好且简单的方法,因为这将比 parse_url 快得多,而且 CPU 密集度也更低。权衡是它不检查现有的 $varName。
    • 经典错误是直接在 if 子句中使用 strpos() return。 $url .= (strpos($url, '?') === false ? '?' : '&').'category=action'; 在性能方面使用单引号会更好。除此之外,此解决方案更符合要求。
    【解决方案3】:

    基本方法

    $query = parse_url($url, PHP_URL_QUERY);
    
    // Returns a string if the URL has parameters or NULL if not
    if ($query) {
        $url .= '&category=1';
    } else {
        $url .= '?category=1';
    }
    

    更高级

    $url = 'http://example.com/search?keyword=test&category=1&tags[]=fun&tags[]=great';
    
    $url_parts = parse_url($url);
    // If URL doesn't have a query string.
    if (isset($url_parts['query'])) { // Avoid 'Undefined index: query'
        parse_str($url_parts['query'], $params);
    } else {
        $params = array();
    }
    
    $params['category'] = 2;     // Overwrite if exists
    $params['tags'][] = 'cool';  // Allows multiple values
    
    // Note that this will url_encode all values
    $url_parts['query'] = http_build_query($params);
    
    // If you have pecl_http
    echo http_build_url($url_parts);
    
    // If not
    echo $url_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path'] . '?' . $url_parts['query'];
    

    如果不是类,你至少应该把它放在一个函数中。

    【讨论】:

    • 别忘了追加category的值
    • @DougT。并非所有参数都需要一个值。例如,?logout 可以使用isset($_GET["logout"]) 进行检查
    • 当您知道 'category' 参数不在 URL 中时,这种方法很好。如果参数已经在 URL 中,那么 PHP 应该采用 URL 中参数最后一次出现的值,所以@andrewtweber 的解决方案仍然有效。然而,我更喜欢下面的解决方案stackoverflow.com/a/4101638/99256
    • -1 表示如果参数已经存在则不替换它。问题中没有明确提及,但在逻辑和语义上是强制性的。
    • 只需使用:echo http_build_url($url, array("query" => "the=query&parts=here"), HTTP_URL_JOIN_QUERY);。但是您需要pecl install pecl_http 或通过composer 安装jakeasmith/http_build_url
    【解决方案4】:
    $data = array('foo'=>'bar',
                  'baz'=>'boom',
                  'cow'=>'milk',
                  'php'=>'hypertext processor');
    
    $queryString =  http_build_query($data);
    //$queryString = foo=bar&baz=boom&cow=milk&php=hypertext+processor
    
    echo 'http://domain.com?'.$queryString;
    //output: http://domain.com?foo=bar&baz=boom&cow=milk&php=hypertext+processor
    

    【讨论】:

    • 只需使用:echo http_build_url($url, array("query" => "the=query&parts=here"), HTTP_URL_JOIN_QUERY);。但是您需要pecl install pecl_http 或通过composer 安装jakeasmith/http_build_url
    【解决方案5】:

    我认为你应该这样做。

    class myURL {
        protected $baseURL, $requestParameters;
    
        public function __construct ($newURL) {
            $this->baseurl = $newURL;
            $this->requestParameters = array();
        }
    
        public function addParameter ($parameter) {
            $this->requestParameters[] = $parameter;
        }
    
        public function __toString () {
            return $this->baseurl.
                   ( count($this->requestParameters) ?
                     '?'.implode('&', $this->requestParameters) :
                     ''
                     );
        }
    }
    
    $url1 = new myURL ('http://www.acme.com');
    $url2 = new myURL ('http://www.acme.com');
    $url2->addParameter('sort=popular');
    $url2->addParameter('category=action');
    $url1->addParameter('category=action');
    
    echo $url1."\n".$url2;
    

    【讨论】:

      【解决方案6】:

      此函数覆盖现有参数

      function addToURL( $key, $value, $url) {
          $info = parse_url( $url );
          parse_str( $info['query'], $query );
          return $info['scheme'] . '://' . $info['host'] . $info['path'] . '?' . http_build_query( $query ? array_merge( $query, array($key => $value ) ) : array( $key => $value ) );
      }
      

      【讨论】:

      • 如果没有设置$info['query']会怎样?你没有考虑到这一点。
      • 如果未设置,$info['query'] 变为 NULL,$query 变为空数组。所以这不是问题。
      【解决方案7】:

      这是已接受答案的简短版本:

      $url .= (parse_url($url, PHP_URL_QUERY) ? '&' : '?') . 'category=action';
      

      编辑:正如在接受的答案中所讨论的,这是有缺陷的,因为它不检查category 是否已经存在。一个更好的解决方案是将$_GET 视为一个数组,并使用in_array() 之类的函数。

      【讨论】:

      • 请注意,这只适用于单个添加的参数,否则它将附加一个 ?如果没有原始查询。
      • @Mgamerz 除非我误解了你,否则这就是 OP 所要求的。由于=之前的.,它可以多次工作。
      • 但是如果你向 url 添加一个参数(因此添加一个?),则不会查询不存在,如果你再次这样做,它会添加另一个? (除非你应该再次运行第一行)? $query 如何更新?
      • @Mgamerz 我明白你现在的意思了。是的,您每次都需要重复第一行来检查$url 是否已经有参数。已编辑。
      • 不处理带有 # 的 URL。
      【解决方案8】:

      更新现有参数的示例。

      还使用了 url_encode,并且可能不指定参数值

          <?
          /**
           * Add parameter to URL
           * @param string $url
           * @param string $key
           * @param string $value
           * @return string result URL
           */
          function addToUrl($url, $key, $value = null) {
              $query = parse_url($url, PHP_URL_QUERY);
              if ($query) {
                  parse_str($query, $queryParams);
                  $queryParams[$key] = $value;
                  $url = str_replace("?$query", '?' . http_build_query($queryParams), $url);
              } else {
                  $url .= '?' . urlencode($key) . '=' . urlencode($value);
              }
              return $url;
          }
      

      【讨论】:

        【解决方案9】:
         /**
         * @example addParamToUrl('/path/to/?find=1', array('find' => array('search', 2), 'FILTER' => 'STATUS'))
         * @example addParamToUrl('//example.com/path/to/?find=1', array('find' => array('search', 2), 'FILTER' => 'STATUS'))
         * @example addParamToUrl('https://example.com/path/to/?find=1&FILTER=Y', array('find' => array('search', 2), 'FILTER' => 'STATUS'))
         *
         * @param       $url string url
         * @param array $addParams
         *
         * @return string
         */
        function addParamToUrl($url, array $addParams) {
          if (!is_array($addParams)) {
            return $url;
          }
        
          $info = parse_url($url);
        
          $query = array();
        
          if ($info['query']) {
            parse_str($info['query'], $query);
          }
        
          if (!is_array($query)) {
            $query = array();
          }
        
          $params = array_merge($query, $addParams);
        
          $result = '';
        
          if ($info['scheme']) {
            $result .= $info['scheme'] . ':';
          }
        
          if ($info['host']) {
            $result .= '//' . $info['host'];
          }
        
          if ($info['path']) {
            $result .= $info['path'];
          }
        
          if ($params) {
            $result .= '?' . http_build_query($params);
          }
        
          return $result;
        }
        

        【讨论】:

          【解决方案10】:

          在搜索了有关此主题的许多资源/答案后,我决定自己编写代码。根据@TaylorOtwell 在此处的回答,这就是我处理传入 $_GET 请求并修改/操作每个元素的方式。

          假设网址为:http://domain.com/category/page.php?a=b&x=y 而且我只想要一个用于排序的参数:?desc=column_name 或 ?asc=column_name。这样,单个 url 参数就足以同时进行排序和排序。因此,在第一次单击关联的表头行时,URL 将为http://domain.com/category/page.php?a=b&x=y&desc=column_name

          然后我有表格行标题,我想在第一次单击时对 DESC 进行排序,并在第二次单击同一标题时对 ASC 进行排序。 (每次第一次点击应该先“ORDER BY column DESC”)如果没有排序,默认按“date then id”排序。

          您可以进一步改进它,例如您可以为每个 $_GET 组件添加清理/过滤功能,但下面的结构奠定了基础。

          foreach ($_GET AS $KEY => $VALUE){
              if ($KEY == 'desc'){
                  $SORT = $VALUE;
                  $ORDER = "ORDER BY $VALUE DESC";
                  $URL_ORDER = $URL_ORDER . "&asc=$VALUE";
              } elseif ($KEY == 'asc'){
                  $SORT = $VALUE;
                  $ORDER = "ORDER BY $VALUE ASC";
                  $URL_ORDER = $URL_ORDER . "&desc=$VALUE";
              } else {
                  $URL_ORDER .= "&$KEY=$VALUE";
                  $URL .= "&$KEY=$VALUE";
              }
          }
          if (!$ORDER){$ORDER = 'ORDER BY date DESC, id DESC';}
          if ($URL_ORDER){$URL_ORDER = $_SERVER[SCRIPT_URL] . '?' . trim($URL_ORDER, '&');}
          if ($URL){$URL = $_SERVER[SCRIPT_URL] . '?' . trim($URL, '&');}
          

          (您可以使用 $_SERVER[SCRIPT_URI] 获取以http://domain.com 开头的完整 URL)

          然后我在 MySQL 查询中使用上面得到的 $ORDER:

          "SELECT * FROM table WHERE limiter = 'any' $ORDER";
          

          现在,如果有先前的排序,则查看 URL 的功能,并使用“?”将排序(和排序)参数添加到 URL或“&”按顺序排列:

                  function sort_order ($_SORT){
                      global $SORT, $URL_ORDER, $URL;
                      if ($SORT == $_SORT){
                          return $URL_ORDER;
                      } else {
                          if (strpos($URL, '?') !== false){
                              return "$URL&desc=$_SORT";
                          } else {                        
                              return "$URL?desc=$_SORT";
                          }
                      }
                  }
          

          最后是表格行头要使用的功能:

                  echo "<th><a href='".sort_order('id')."'>ID</a></th>";
          

          总结:这将读取 URL,修改每个 $_GET 组件,并使用您选择的参数以正确的“?”使用形式制作最终 URL和“&”

          【讨论】:

            【解决方案11】:
            <?php
            $url1 = '/test?a=4&b=3';
            $url2 = 'www.baidu.com/test?a=4&b=3&try_count=1';
            $url3 = 'http://www.baidu.com/test?a=4&b=3&try_count=2';
            $url4 = '/test';
            function add_or_update_params($url,$key,$value){
                $a = parse_url($url);
                $query = $a['query'] ? $a['query'] : '';
                parse_str($query,$params);
                $params[$key] = $value;
                $query = http_build_query($params);
                $result = '';
                if($a['scheme']){
                    $result .= $a['scheme'] . ':';
                }
                if($a['host']){
                    $result .= '//' . $a['host'];
                }
                if($a['path']){
                    $result .=  $a['path'];
                }
                if($query){
                    $result .=  '?' . $query;
                }
                return $result;
            }
            echo add_or_update_params($url1,'try_count',1);
            echo "\n";
            echo add_or_update_params($url2,'try_count',2);
            echo "\n";
            echo add_or_update_params($url3,'try_count',3);
            echo "\n";
            echo add_or_update_params($url4,'try_count',4);
            echo "\n";
            

            【讨论】:

            • 干得好,只用$query = isset($a['query']) ? $a['query'] : '';替换行$query = $a['query'] ? $a['query'] : '';
            【解决方案12】:
             public function addGetParamToUrl($url, $params)
            {
                foreach ($params as $param) {
                     if (strpos($url, "?"))
                    {
                        $url .= "&" .http_build_query($param); 
                    }
                    else
                    {
                        $url .= "?" .http_build_query($param); 
                    }
                }
                return $url;
            }
            

            【讨论】:

              【解决方案13】:

              另一个改进的功能版本。现有答案与小改进(端口支持)和错误修复(正确检查密钥)相结合。

              /**
               * @param string $url original url to modify - can be relative, partial etc
               * @param array $paramsOverride associative array, can be empty
               * @return string modified url
               */
              protected function overrideUrlQueryParams($url, $paramsOverride){
                  if (!is_array($paramsOverride)){
                      return $url;
                  }
              
                  $url_parts = parse_url($url);
              
                  if (isset($url_parts['query'])) {
                      parse_str($url_parts['query'], $params);
                  } else {
                      $params = [];
                  }
              
                  $params = array_merge($params, $paramsOverride);
              
                  $res = '';
              
                  if(isset($url_parts['scheme'])) {
                      $res .= $url_parts['scheme'] . ':';
                  }
              
                  if(isset($url_parts['host'])) {
                      $res .= '//' . $url_parts['host'];
                  }
              
                  if(isset($url_parts['port'])) {
                      $res .= ':' . $url_parts['port'];
                  }
              
                  if (isset($url_parts['path'])) {
                      $res .= $url_parts['path'];
                  }
              
                  if (count($params) > 0) {
                      $res .= '?' . http_build_query($params);
                  }
              
                  return $res;
              }
              

              【讨论】:

                【解决方案14】:

                试试这个功能添加网址参数

                然后您可以在设置参数时禁用链接,这样就不会有url参数重复。

                <?php
                  function addQueryString($a)
                                {
                             if (empty($_SERVER['QUERY_STRING']))
                               return '?' . $a;
                             else if (!empty($_SERVER['QUERY_STRING']))
                              return '?' . $_SERVER['QUERY_STRING'] . '&' . $a;
                                }
                ?>
                
                 <a href="<?php echo addQueryString('lang=en'); ?>">test</a>
                 <a href="<?php echo addQueryString('category=5'); ?>">sat</a>
                

                【讨论】:

                  【解决方案15】:

                  如果您使用的是 WordPress,您可以简单地使用

                      add_query_args(['sort' => 'asc'], 'http:/example.com/?search=news')
                  

                  文档https://developer.wordpress.org/reference/functions/add_query_arg/

                  【讨论】:

                    【解决方案16】:

                    单线:

                    $url .= (strpos($url, '?') ? '&' : '?') . http_build_query($additionalParams);
                    

                    推荐使用http_build_query,因为它会编码特殊字符(例如电子邮件地址中的空格或@

                    【讨论】:

                      猜你喜欢
                      • 2010-11-06
                      • 2021-11-12
                      • 2022-07-25
                      • 2021-03-09
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2012-01-18
                      • 2017-06-18
                      相关资源
                      最近更新 更多