从URL的查询字符串中删除特定参数

56

我在Powerpoint演示文稿中有一些链接,但是点击这些链接时,它们会向URL中添加一个返回参数。然而,该返回参数导致我的Joomla站点的MVC模式出现问题。

有没有一种有效的使用PHP去除此返回参数的方法?

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


可能是使用PHP删除GET变量的美妙方法?的重复问题。 - PiTheNumber
24个回答

115

最安全的“正确”方法如下:

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

快速且简单的方法是使用字符串搜索/替换和/或正则表达式来删除值。


3
奇怪,我的$parsedurl['query']是一个单字符串,包含所有参数。 - ajax333221
请删除PHP中GET变量的优美方法 - Ari
1
你能举一个脏正则表达式失败的场景例子吗? - Vincent
2
请举个例子? - Jones G
2
parse_url()存在漏洞,完全不安全,不建议使用。 - holden321

94

9
如何删除特定的GET变量return而不是删除所有GET变量。 - mgutt

35

这是为了补充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);

谢谢Sergey,也感谢@Marc B的出色帮助。 - luke_mclachlan
3
评论:如果有人在使用此代码时,请注意该代码仅返回查询字符串(减去您删除的参数)。如果您需要完整的URL地址,则无法得到它。 - Codemonkey

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

3
最佳答案。 - Vahid Amiri
太棒了。谢谢! - dnns
同意,这正是我在寻找的。正则表达式是我的弱点,但我知道这就是我需要的答案。 - ctrlbrk
如果URL在目标参数后面有一个#哈希,这个函数也会将其去掉。小心复制/粘贴,这个答案已经存在了8年,在一个拥有150k浏览量且没有人注意到的问题上。 - Maciej Krawczyk
嗯,看起来大部分这里的答案都会去掉井号。 - Maciej Krawczyk

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

parse_str函数可以将查询字符串解析为参数数组,http_build_query函数则可以将参数数组转换为查询字符串。


12

在精简Sergey Telshevsky的回答后,按照Marc B的方案实现。

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

1
当传入一个没有查询字符串的URL时会导致错误。 - Jason Engage
它还保留了“?”这可能会在后面引起问题 - Chris Pink

9
您可以使用preg_replace函数,例如:
$new_url = preg_replace('/&?return=[^&]*/', '', $old_url);

4
如果"?return="不是最后一个参数,这样做不是一个好主意。像"urlerror.com/index.php?return=1&test=abc" 这样的查询将被更改为 "urlerror.com/index.php&test=abc"。 - kraftb
preg_replace('/return=[^&]?&?/i', '', $_SERVER['REQUEST_URI'); - Chris Greenwood
这个答案是错误的。分析:https://dev59.com/p2445IYBdhLWcg3wTIZf#47527628 - mgutt

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()避免通过http_build_query()函数进行两次编码。 注意:已更新使用ksort()以允许没有值的参数不会出现错误。

1
很棒的例子!提醒其他人:$kill_params数组中的“gclid”是将从URI的查询字符串部分中删除的内容。还要注意,重建URL的这种方法可能不完整。此外,我刚刚发现另一种方法可能比使用parse_url()更适合拆分和重新组合更现代的URI;在这里:http://nadeausoftware.com/articles/2008/05/php_tip_how_parse_and_build_urls - Damian Green

5
这是其中一种方法,未经测试,但应该可以正常工作。
$link = 'http://mydomain.example/index.php?id=115&Itemid=283&return=aHR0cDovL2NvbW11bml0';
$linkParts = explode('&return=', $link);
$link = $linkParts[0];

2
这个解决方案假设return在最后一个位置,如果不是这样的话,你将失去return参数中的所有其他参数。 - Dr. House

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

?>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接