从 URL 的查询字符串中剥离特定参数

问题描述 投票:0回答:22

我在 Powerpoint 演示文稿中有一些链接,出于某种原因,当这些链接被点击时,它会向 URL 添加一个返回参数。好吧,那个返回参数导致我的 Joomla 网站的 MVC 模式搞砸了。

使用 PHP 去除此返回参数的有效方法是什么?

例子:

http://mydomain.example/index.php?id=115&Itemid=283&return=aHR0cDovL2NvbW11bml0

php model-view-controller joomla query-string
22个回答
111
投票

最安全的“正确”方法是:

  1. 使用
    parse_url()
  2. 将 url 解析为数组
  3. 提取查询部分,使用
    parse_str()
  4. 将其分解为数组
  5. 通过
    unset()
    从数组中删除您想要的查询参数
  6. 使用
    http_build_query()
  7. 重建原始网址

快速而肮脏的方法是使用字符串搜索/替换和/或正则表达式来消除值。


91
投票

在另一个线程中,Justin 建议最快的方法是使用 strtok()

 $url = strtok($url, '?');

在这里也可以看到他对速度测试的完整回答:https://stackoverflow.com/a/1251650/452515


32
投票

这是用一个例子来补充Marc B的答案,虽然它看起来很长,但它是删除参数的安全方法。在这个例子中,我们删除了

page_number

<?php
$x = 'http://url.example/search/?location=london&page_number=1';

$parsed = parse_url($x);
$query = $parsed['query'];

parse_str($query, $params);

unset($params['page_number']);
$string = http_build_query($params);
var_dump($string);

16
投票
function removeParam($url, $param) {
    $url = preg_replace('/(&|\?)'.preg_quote($param).'=[^&]*$/', '', $url);
    $url = preg_replace('/(&|\?)'.preg_quote($param).'=[^&]*&/', '$1', $url);
    return $url;
}

14
投票
parse_str($queryString, $vars);
unset($vars['return']);
$queryString = http_build_query($vars);

parse_str
解析查询字符串,
http_build_query
创建查询字符串。


11
投票

Marc B 的 精炼后的答案Sergey Telshevsky 的 答案的程序实施。

function strip_param_from_url($url, $param)
{
    $base_url = strtok($url, '?');                   // Get the base URL
    $parsed_url = parse_url($url);                   // Parse it
                               // Add missing {
    if(array_key_exists('query',$parsed_url)) {      // Only execute if there are parameters
        $query = $parsed_url['query'];               // Get the query string
        parse_str($query, $parameters);              // Convert Parameters into array
        unset($parameters[$param]);                  // Delete the one you want
        $new_query = http_build_query($parameters);  // Rebuilt query string
        $url =$base_url.'?'.$new_query;              // Finally URL is ready
    }
    return $url;            
}

// Usage
echo strip_param_from_url( 'http://url.example/search/?location=london&page_number=1', 'location' )

9
投票

你可以做一个

preg_replace
像:

$new_url = preg_replace('/&?return=[^&]*/', '', $old_url);

7
投票

这是上面描述的“最安全的‘正确’方法”的实际代码……

function reduce_query($uri = '') {
    $kill_params = array('gclid');

    $uri_array = parse_url($uri);
    if (isset($uri_array['query'])) {
        // Do the chopping.
        $params = array();
        foreach (explode('&', $uri_array['query']) as $param) {
          $item = explode('=', $param);
          if (!in_array($item[0], $kill_params)) {
            $params[$item[0]] = isset($item[1]) ? $item[1] : '';
          }
        }
        // Sort the parameter array to maximize cache hits.
        ksort($params);
        // Build new URL (no hosts, domains, or fragments involved).
        $new_uri = '';
        if ($uri_array['path']) {
          $new_uri = $uri_array['path'];
        }
        if (count($params) > 0) {
          // Wish there was a more elegant option.
          $new_uri .= '?' . urldecode(http_build_query($params));
        }
        return $new_uri;
    }
    return $uri;
}

$_SERVER['REQUEST_URI'] = reduce_query($_SERVER['REQUEST_URI']);

但是,由于这可能在您的应用程序启动之前就已经存在,您应该将它放入一个匿名函数中。像这样……

call_user_func(function($uri) {
    $kill_params = array('gclid');

    $uri_array = parse_url($uri);
    if (isset($uri_array['query'])) {
        // Do the chopping.
        $params = array();
        foreach (explode('&', $uri_array['query']) as $param) {
          $item = explode('=', $param);
          if (!in_array($item[0], $kill_params)) {
            $params[$item[0]] = isset($item[1]) ? $item[1] : '';
          }
        }
        // Sort the parameter array to maximize cache hits.
        ksort($params);
        // Build new URL (no hosts, domains, or fragments involved).
        $new_uri = '';
        if ($uri_array['path']) {
          $new_uri = $uri_array['path'];
        }
        if (count($params) > 0) {
          // Wish there was a more elegant option.
          $new_uri .= '?' . urldecode(http_build_query($params));
        }
        // Update server variable.
        $_SERVER['REQUEST_URI'] = $new_uri;

    }
}, $_SERVER['REQUEST_URI']);

注意:使用

urldecode()
更新以避免双重编码
via http_build_query()
功能。 注意:使用
ksort()
更新以允许没有值的参数没有错误。


6
投票

这是众多方法之一,未经测试,但应该有效。

$link = 'http://mydomain.example/index.php?id=115&Itemid=283&return=aHR0cDovL2NvbW11bml0';
$linkParts = explode('&return=', $link);
$link = $linkParts[0];

4
投票

哇,这里有很多例子。我提供了一个做一些错误处理的。它重建并返回整个 URL,其中包含要删除的查询字符串参数,已删除。它还提供了一个额外的功能,可以动态构建当前 URL。经过测试,有效!

感谢 Mark B 的步骤。这是 tpow 的“剥离此返回参数”原始问题的完整解决方案——对于试图避免 PHP 陷阱的初学者来说可能很方便。 :-)

<?php

function currenturl_without_queryparam( $queryparamkey ) {
    $current_url = current_url();
    $parsed_url = parse_url( $current_url );
    if( array_key_exists( 'query', $parsed_url )) {
        $query_portion = $parsed_url['query'];
    } else {
        return $current_url;
    }

    parse_str( $query_portion, $query_array );

    if( array_key_exists( $queryparamkey , $query_array ) ) {
        unset( $query_array[$queryparamkey] );
        $q = ( count( $query_array ) === 0 ) ? '' : '?';
        return $parsed_url['scheme'] . '://' . $parsed_url['host'] . $parsed_url['path'] . $q . http_build_query( $query_array );
    } else {
        return $current_url;
    }
}

function current_url() {
    $current_url = 'http' . (isset($_SERVER['HTTPS']) ? 's' : '') . '://' . "{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
    return $current_url;
}

echo currenturl_without_queryparam( 'key' );

?>

3
投票
$var = preg_replace( "/return=[^&]+/", "", $var );
$var = preg_replace( "/&{2,}/", "&", $var );

第二行将 && 替换为 &


3
投票

很简单

$link = "http://example.com/index.php?id=115&Itemid=283&return=aHR0cDovL2NvbW11bml0"
echo substr($link, 0, strpos($link, "return") - 1);
//output : http://example.com/index.php?id=115&Itemid=283

3
投票

@MarcB 提到使用正则表达式删除 url 参数是很脏的。是的,因为它并不像看起来那么容易:

$urls = array(
  'example.com/?foo=bar',
  'example.com/?bar=foo&foo=bar',
  'example.com/?foo=bar&bar=foo',
);

echo 'Original' . PHP_EOL;
foreach ($urls as $url) {
  echo $url . PHP_EOL;
}

echo PHP_EOL . '@AaronHathaway' . PHP_EOL;
foreach ($urls as $url) {
  echo preg_replace('#&?foo=[^&]*#', null, $url) . PHP_EOL;
}

echo PHP_EOL . '@SergeS' . PHP_EOL;
foreach ($urls as $url) {
  echo preg_replace( "/&{2,}/", "&", preg_replace( "/foo=[^&]+/", "", $url)) . PHP_EOL;
}

echo PHP_EOL . '@Justin' . PHP_EOL;
foreach ($urls as $url) {
  echo preg_replace('/([?&])foo=[^&]+(&|$)/', '$1', $url) . PHP_EOL;
}

echo PHP_EOL . '@kraftb' . PHP_EOL;
foreach ($urls as $url) {
  echo preg_replace('/(&|\?)foo=[^&]*&/', '$1', preg_replace('/(&|\?)foo=[^&]*$/', '', $url)) . PHP_EOL;
}

echo PHP_EOL . 'My version' . PHP_EOL;
foreach ($urls as $url) {
  echo str_replace('/&', '/?', preg_replace('#[&?]foo=[^&]*#', null, $url)) . PHP_EOL;
}

退货:

原创
example.com/?foo=bar
example.com/?bar=foo&foo=bar
example.com/?foo=bar&bar=foo

@亚伦海瑟薇
example.com/?
example.com/?bar=foo
example.com/?&bar=foo

@SergeS
example.com/?
example.com/?bar=foo&
example.com/?&bar=foo

@贾斯汀
example.com/?
example.com/?bar=foo&
example.com/?bar=foo

@kraftb
example.com/
example.com/?bar=foo
example.com/?bar=foo

我的版本
example.com/
example.com/?bar=foo
example.com/?bar=foo

如您所见,只有@kraftb 使用正则表达式发布了正确答案,而我的版本有点小。


2
投票

从当前页面删除获取参数

<?php
$url_dir=$_SERVER['REQUEST_URI']; 

$url_dir_no_get_param= explode("?",$url_dir)[0];

echo $_SERVER['HTTP_HOST'].$url_dir_no_get_param;

1
投票

应该这样做:

public function removeQueryParam(string $url, string $param): string
{
    $parsedUrl = parse_url($url);

    if (isset($parsedUrl[$param])) {
        $baseUrl = strtok($url, '?');
        parse_str(parse_url($url)['query'], $query);
        unset($query[$param]);
        return sprintf('%s?%s',
            $baseUrl,
            http_build_query($query)
        );
    }

    return $url;
}

1
投票

适用于每个网址的简单解决方案

有了这个解决方案

$url
格式或参数位置并不重要,例如我在
$url
的末尾添加了另一个参数和锚点:

https://example.com/index.php?id=115&Itemid=283&return=aHR0cDovL2NvbW11bml0&bonus=test#test2

这是简单的解决方案:

$url = 'https://example.com/index.php?id=115&Itemid=283&return=aHR0cDovL2NvbW11bml0&bonus=test#test2';

$url_query_stirng = parse_url($url, PHP_URL_QUERY);
parse_str( $url_query_stirng, $url_parsed_query );
unset($url_parsed_query['return']);
$url = str_replace( $url_query_stirng, http_build_query( $url_parsed_query ), $url );

echo $url;

$url
字符串的最终结果是:

https://example.com/index.php?id=115&Itemid=283&bonus=test#test2

1
投票

发布的一些示例非常广泛。这就是我在我的项目中使用的。

function removeQueryParameter($url, $param){
    list($baseUrl, $urlQuery) = explode('?', $url, 2);
    parse_str($urlQuery, $urlQueryArr);
    unset($urlQueryArr[$param]);

    if(count($urlQueryArr))
        return $baseUrl.'?'.http_build_query($urlQueryArr);
    else
        return $baseUrl;
}

0
投票
function remove_attribute($url,$attribute)
 {
    $url=explode('?',$url);
    $new_parameters=false;
    if(isset($url[1]))
    {
        $params=explode('&',$url[1]);
        $new_parameters=ra($params,$attribute);
    }
    $construct_parameters=($new_parameters && $new_parameters!='' ) ? ('?'.$new_parameters):'';
    return $new_url=$url[0].$construct_parameters;
 }
 function ra($params,$attr)
    {   $attr=$attr.'=';
        $new_params=array();

        for($i=0;$i<count($params);$i++)
        {   
            $pos=strpos($params[$i],$attr);

            if($pos===false)
            $new_params[]=$params[$i];

        }
        if(count($new_params)>0)
        return implode('&',$new_params);
        else 
        return false; 
     }

//只需复制上面的代码并像这样调用此函数即可获得没有特定参数的新网址

echo remove_attribute($url,'delete_params'); // 给出没有该参数的新 url


0
投票

我知道这是一个老问题,但如果你只想删除一个或几个命名的 url 参数,你可以使用这个函数:

function RemoveGet_Regex($variable, $rewritten_url): string {
    $rewritten_url = preg_replace("/(\?)$/", "", preg_replace("/\?&/", "?", preg_replace("/((?<=\?)|&){$variable}=[\w]*/i", "", $rewritten_url)));
    return $rewritten_url;
}
function RemoveGet($name): void {
    $rewritten_url = "https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
    if(is_array($name)) {
        for($i = 0; $i < count($name); $i++) {
            $rewritten_url = RemoveGet_Regex($name[$i], $rewritten_url);
            $is_set[] = isset($_GET[$name[$i]]);
        }
        $array_filtered = array_filter($is_set);
        if (!empty($array_filtered)) {
            header("Location: ".$rewritten_url);
        }
    }
    else {
        $rewritten_url = RemoveGet_Regex($name, $rewritten_url);
        if(isset($_GET[$name])) {
            header("Location: ".$rewritten_url);
        }
    }
}

在第一个函数中

preg_replace("/((?<=\?)|&){$variable}=[\w]*/i", "", $rewritten_url)
会去掉get参数,其他的会整理一下。然后第二个函数将重定向。

RemoveGet("id");
将从 url 中删除
id=whatever
。该函数还可以与数组一起使用。对于你的例子,

Remove(array("id","Item","return"));


0
投票

要使用 PHP 脚本从 url 中删除任何参数,您需要遵循以下脚本:

 function getNewArray($array,$k){
        $dataArray = $array;
        unset($array[$k]);
        $dataArray = $array;
        return $dataArray;  
    }
    
function getFullURL(){
        return (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
    }

 

     $url = getFullURL(); 
      $url_components = parse_url($url);
      
      // Use parse_str() function to parse the
      // string passed via URL
      parse_str($url_components['query'], $params);
      print_r($params); 

    <ul>
    <?php foreach($params as $k=>$v){?>
    <?php 
    
    $newArray = getNewArray($params,$k);
    $parameters  = http_build_query($newArray);
    $newURL = $_SERVER['PHP_SELF']."?".$parameters;
     ?>
    <li><?=$v;?> <a href="<?=$newURL;?>">X</a>
    <?php }?>
    </ul>

0
投票

这里是针对速度优化的功能。但是这个函数不会删除像'a[]=x&a[1]=y&a[2]=z'这样的数组。如果您需要任何情况下的完整模式 - 请评论我。

function removeQueryParam($query, $param)
{
    $quoted_param = preg_quote($param, '/');
    $pattern = "/(^$quoted_param=[^&]*&?)|(&$quoted_param=[^&]*)/";
    return preg_replace($pattern, '', $query);
}

function removeQueryParams($query, array $params)
{
    if ($params)
    {
        $pattern = '/';
        foreach ($params as $param)
        {
            $quoted_param = preg_quote($param, '/');
            $pattern .= "(^$quoted_param=[^&]*&?)|(&$quoted_param=[^&]*)|";
        }
        $pattern[-1] = '/';
        return preg_replace($pattern, '', $query);  
    }
    return $query;
}

-1
投票
<? if(isset($_GET['i'])){unset($_GET['i']); header('location:/');} ?>

这将从 URL 中删除“i”参数。将“i”更改为您需要的任何内容。

© www.soinside.com 2019 - 2024. All rights reserved.