使用PHP

时间:2017-12-14 20:18:04

标签: php regex url get

我一直在使用以下函数来长时间删除get参数:

function removeGetParameter($url, $varname) {
    return preg_replace('/([?&])'.$varname.'=[^&]+(&|$)/','$1',$url);
}

(摘自this thread

但我注意到如果我删除所有参数,我会在字符串的末尾加上一个问号后缀?。如果在字符串的末尾找到?,我不能修剪它,因为它可能是另一个GET参数的值(即http://example.com?myquestion=are+you+here?)。

我提出了这个解决方案,但我怀疑它的效率。

function removeGetParameter($url, $varname) {
    $p = parse_url($url);
    parse_str($p['query'], $vars);
    unset($vars[$varname]);
    $vars_str = (count($vars) ? '?':'').http_build_query($vars);
    return $p['scheme'].'://'.$p['host'].$vars_str;
}

它完成了工作,但我相信它比许多其他选项慢。

是否有任何通用,安全的方法从给定的URL中删除特定的GET参数?

谢谢!

修改:我添加了if条款更安全(我们可能根本没有变量)

function removeGetParameter($url, $varname) {

    $p = parse_url($url); // parse the url to parts.
    $final = $p['scheme'].'://'.$p['host']; // build the url from the protocol and host.

    if(!empty($p['query'])) { // if we have any get parameters
        parse_str($p['query'], $vars); // make an array of them ($vars)
        unset($vars[$varname]); // unset the wanted
        $vars_str = (count($vars) ? '?':'').http_build_query($vars); // if has any variables, add a question mark
        return $final.$vars_str; // merge all together
    } else {
        return $final; // no variables needed.
    }
}

这是最佳解决方案吗?

2 个答案:

答案 0 :(得分:2)

好吧,我的最终代码:

function removeGetParameter($url, $varname) {
    $p = parse_url($url); // parse the url to parts.

    parse_str($p['query'] ?? '', $vars); // make an array of the parameters if exist ($vars)
    unset($vars[$varname]); // unset the unwanted
    $vars_str = http_build_query($vars); // build the query string

    return unparse_url($p, $vars_str);
}


function unparse_url($p, $custom_query = NULL) {
    // my customization to http://php.net/manual/en/function.parse-url.php thomas at gielfeldt dot com
    $scheme   = isset($p['scheme']) ? $p['scheme'] . '://' : '';
    $host     = isset($p['host']) ? $p['host'] : '';
    $port     = isset($p['port']) ? ':' . $p['port'] : '';
    $user     = isset($p['user']) ? $p['user'] : '';
    $pass     = isset($p['pass']) ? ':' . $p['pass']  : '';
    $pass     = ($user || $pass) ? "$pass@" : '';
    $path     = isset($p['path']) ? $p['path'] : '';

    $toquery = $custom_query ?? ($p['query'] ?? ''); // get query string -> the given one, or the one that already exists.
    $query    = (strlen($toquery) > 0 ? '?'.$toquery : ''); // add the question mark only if has query.

    $fragment = isset($p['fragment']) ? '#' . $p['fragment'] : '';

    return "$scheme$user$pass$host$port$path$query$fragment";
}

非常感谢你的帮助:))

答案 1 :(得分:-1)

你是对的。正则表达式版本更快,即使使用另一个包装正则表达式来处理烦人的问题?最后:

<?php
set_time_limit(0);

$url = 'http://google.com/?teste=waldson&name=patricio';

function removeGetParameter($url, $varname) {
    return preg_replace('#\\?$#', '', preg_replace('/([?&])'.$varname.'=[^&]+(&|$)/','$1',$url));
}

function removeGetParameter2($url, $varname) {
    $p = parse_url($url);
    parse_str($p['query'], $vars);
    unset($vars[$varname]);
    $vars_str = (count($vars) ? '?':'').http_build_query($vars);
    return $p['scheme'].'://'.$p['host'].$vars_str;
}


$startTime = microtime(TRUE);
for ($i = 0; $i < 300000; ++$i) {
    removeGetParameter($url, 'teste');
    removeGetParameter($url, 'name');
}
$totalTime = microtime(true) - $startTime;


$startTime2 = microtime(TRUE);
for ($i = 0; $i < 300000; ++$i) {
    removeGetParameter2($url, 'teste');
    removeGetParameter2($url, 'name');
}
$totalTime2 = microtime(true) - $startTime2;


echo 'Time regex: '  . $totalTime . '<br />';
echo 'Time parse_url: '  . $totalTime2;

我得到了这些结果:

Time regex: 2.1999499797821
Time parse_url: 2.8799331188202

removeGetParameter的此修改版本应该可以完成工作。