如何删除查询字符串并仅获取URL?


201

我使用PHP来构建当前页面的URL。有时,URL的形式为

www.mydomian.com/myurl.html?unwantedthngs

被要求。我想删除?和其后的所有内容(查询字符串),以使最终的URL变为:

www.mydomain.com/myurl.html

我当前的代码是这样的:

<?php
function curPageURL() {
    $pageURL = 'http';
    if ($_SERVER["HTTPS"] == "on") {
        $pageURL .= "s";
    }
    $pageURL .= "://";
    if ($_SERVER["SERVER_PORT"] != "80") {
        $pageURL .= $_SERVER["SERVER_NAME"] . ":" .
            $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
    } else {
        $pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
    }
    return $pageURL;
}
?>

8
顺便说一句,这就是所谓的“查询字符串”。
伊万·穆拉斯基

Answers:


577

您可以用来strtok在第一次出现之前获取字符串?

$url = strtok($_SERVER["REQUEST_URI"], '?');

strtok()代表最简洁的技术来直接?在查询字符串中提取子字符串。 explode()之所以不太直接,是因为它必须产生一个可能包含两个元素的数组,必须通过该数组访问第一个元素。

当查询字符串丢失或可能会使url中的其他/意外子字符串突变时,其他一些技术可能会中断-应该避免使用这些技术。

一个演示

$urls = [
    'www.example.com/myurl.html?unwantedthngs#hastag',
    'www.example.com/myurl.html'
];

foreach ($urls as $url) {
    var_export(['strtok: ', strtok($url, '?')]);
    echo "\n";
    var_export(['strstr/true: ', strstr($url, '?', true)]); // not reliable
    echo "\n";
    var_export(['explode/2: ', explode('?', $url, 2)[0]]);  // limit allows func to stop searching after first encounter
    echo "\n";
    var_export(['substr/strrpos: ', substr($url, 0, strrpos( $url, "?"))]);  // not reliable; still not with strpos()
    echo "\n---\n";
}

输出:

array (
  0 => 'strtok: ',
  1 => 'www.example.com/myurl.html',
)
array (
  0 => 'strstr/true: ',
  1 => 'www.example.com/myurl.html',
)
array (
  0 => 'explode/2: ',
  1 => 'www.example.com/myurl.html',
)
array (
  0 => 'substr/strrpos: ',
  1 => 'www.example.com/myurl.html',
)
---
array (
  0 => 'strtok: ',
  1 => 'www.example.com/myurl.html',
)
array (
  0 => 'strstr/true: ',
  1 => false,                       // bad news
)
array (
  0 => 'explode/2: ',
  1 => 'www.example.com/myurl.html',
)
array (
  0 => 'substr/strrpos: ',
  1 => '',                          // bad news
)
---

24
+1用于直接使用$ _SERVER而不是重建URL只是重新解析它。为简洁起见,如果可能的话,会再提供+1。
ericsoco 2012年

8
糟糕-反转explode()的参数,定界符排在最前面。 array_shift(explode('?',$_SERVER["REQUEST_URI"]))
这里

13
如果不返回bool(false)呢?在字符串中不存在,它将返回字符串。
本C

4
太好了!。即使?不存在,它仍在返回url 。
哈里希南2015年

1
@sepehr,我只是看不到不要使用完全满足您需求的函数,而是使用另一个函数并解析其结果(即爆炸后得到[0])(当然,除非有特定的原因,例如更好的性能) ,缺乏不必要的依赖性等)。
RiaD

66

使用PHP手册-parse_url()获取所需的部分。

编辑(@Navi Gamage的示例用法)

您可以像这样使用它:

<?php
function reconstruct_url($url){    
    $url_parts = parse_url($url);
    $constructed_url = $url_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path'];

    return $constructed_url;
}

?>

编辑(第二个完整示例):

更新功能以确保方案将被附加并且没有通知消息出现:

function reconstruct_url($url){    
    $url_parts = parse_url($url);
    $constructed_url = $url_parts['scheme'] . '://' . $url_parts['host'] . (isset($url_parts['path'])?$url_parts['path']:'');

    return $constructed_url;
}


$test = array(
    'http://www.mydomian.com/myurl.html?unwan=abc',
    'http://www.mydomian.com/myurl.html',
    'http://www.mydomian.com',
    'https://mydomian.com/myurl.html?unwan=abc&ab=1'
);

foreach($test as $url){
    print_r(parse_url($url));
}       

将返回:

Array
(
    [scheme] => http
    [host] => www.mydomian.com
    [path] => /myurl.html
    [query] => unwan=abc
)
Array
(
    [scheme] => http
    [host] => www.mydomian.com
    [path] => /myurl.html
)
Array
(
    [scheme] => http
    [host] => www.mydomian.com
)
Array
(
    [path] => mydomian.com/myurl.html
    [query] => unwan=abc&ab=1
)

这是不带第二个参数的示例URL通过parse_url()传递的输出(仅用于解释)。

这是使用以下命令构造url之后的最终输出:

foreach($test as $url){
    echo reconstruct_url($url) . '<br/>';
}   

输出:

http://www.mydomian.com/myurl.html
http://www.mydomian.com/myurl.html
http://www.mydomian.com
https://mydomian.com/myurl.html

我读了..如果对php不熟悉,我有点困惑,因为上面的php代码可以帮我吗?
Navi Gamage

我在第9行$ pageURL = substr($ pageURL,0,strrpos($ pageURL,“?”))之后添加了此代码;
Navi Gamage,

可以查询网址中的查询部分...> www.mydomain.com/myurl.html?unwantedthings结果还可以!> www.mydomian.com/myurl.html完成......但是,当它与正常的网址> www.mydomain.com/myurl.html结果是nothing..Empty
导航Gamage

“ www.mydomain.com/myurl.html”中的strrpos()将返回0(为更正确,将FALSE 强制转换为布尔值),因此您的substr将为空。使用一个:substr() parse_url(),因为两者都没有意义;)
veritas

我的意思是将FALSE强制转换为int; D
veritas,

54

最佳解决方案:

echo parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

如果您要向同一域提交表单,则无需在您的网站中包含http://domain.com


请注意,parse_url需要一个绝对URL,因此在某些情况下(例如,如果您的REQUEST_URL以多个连续的斜杠开头),您将得到不正确的结果。这些将被解释为相对协议的URI。
NikiC

16
$val = substr( $url, 0, strrpos( $url, "?"));

球员盘带你的答案林done..thanks您help..It cleas查询URL中的部分...
导航Gamage

> www.mydomain.com/myurl.html?unwantedthings结果可以!> www.mydomian.com/myurl.html完成......但是,当它与正常的网址> www.mydomain.com/myurl.html结果是nothing..Empty
导航Gamage

新的PHP代码 code <?php函数curPageURL(){$ pageURL ='http'; if($ _SERVER [“ HTTPS”] ==“ on”){$ pageURL。=“ s”;} $ pageURL。=“://”; 如果($ _SERVER [“ SERVER_PORT”]!=“ 80”){$ pageURL。= $ _SERVER [“ SERVER_NAME”]。“:”。“ $ _ SERVER [” SERVER_PORT“]。$ _ SERVER [” REQUEST_URI“]; } else {$ pageURL。= $ _SERVER [“ SERVER_NAME”]。$ _ SERVER [“ REQUEST_URI”]; $ pageURL = substr($ pageURL,0,strrpos($ pageURL,“?”)); }返回$ pageURL; }?>code
Navi Gamage

2
我认为这是解决该问题的一种很好而又简单的方法。不需要扩展或功能负载。我用它来获取当前调用的文件名。$ base = basename($ _ SERVER ['REQUEST_URI']); $ page = substr($ base,0,strrpos($ base,“?”));
罗布

正如Navi所说,这个答案是不可靠的。3v4l.org/nhVii 如果URL中不存在查询字符串,则将删除整个URL!此技术不支持url组件。 这个答案是不可取的。
mickmackusa

9

最简单的方法

$url = 'https://www.youtube.com/embed/ROipDjNYK4k?rel=0&autoplay=1';
$url_arr = parse_url($url);
$query = $url_arr['query'];
print $url = str_replace(array($query,'?'), '', $url);

//output
https://www.youtube.com/embed/ROipDjNYK4k

我不同意这是最简单的方法。不,粗体文字不会使您的陈述更具说服力。这个答案缺乏解释。
mickmackusa

@mickmackusa您能详细说明一下吗?我需要在哪里解释我的答案?我会感激你的
Mukesh Saxena

关于Stackoverflow的所有答案都应包括解决方案的工作原理以及为什么您认为它是一种理想的技术的解释。也欢迎链接到文档。我完全了解您的解决方案,但其他研究人员可能不知道。纯代码的答案对Stackoverflow而言价值不高,因为它们对教育/授权成千上万的未来研究人员几乎没有作用。关于不是最简单的问题-3v4l.org/RE0GD将是您答案的一个更简单的版本,因为它声明的变量更少,并且只能替换一个而不是两个。公认的答案是最简单的。
mickmackusa

另一个不同之处是,可接受的答案还会处理可能的碎片,但是您不会。 3v4l.org/ERr4V 或更糟糕的是,它可能会破坏
mickmackusa


4

您可以像这样使用parse_url内置函数:

$baseUrl = $_SERVER['SERVER_NAME'] . parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

2

你可以试试:

<?php
$this_page = basename($_SERVER['REQUEST_URI']);
if (strpos($this_page, "?") !== false) $this_page = reset(explode("?", $this_page));
?>

2

如果要获取请求路径(更多信息):

echo parse_url($_SERVER["REQUEST_URI"])['path']

如果您要删除查询,并且(也可能是片段):

function strposa($haystack, $needles=array(), $offset=0) {
        $chr = array();
        foreach($needles as $needle) {
                $res = strpos($haystack, $needle, $offset);
                if ($res !== false) $chr[$needle] = $res;
        }
        if(empty($chr)) return false;
        return min($chr);
}
$i = strposa($_SERVER["REQUEST_URI"], ['#', '?']);
echo strrpos($_SERVER["REQUEST_URI"], 0, $i);

1

要从请求URI中删除查询字符串,请将查询字符串替换为空字符串:

function request_uri_without_query() {
    $result = $_SERVER['REQUEST_URI'];
    $query = $_SERVER['QUERY_STRING'];
    if(!empty($query)) {
        $result = str_replace('?' . $query, '', $result);
    }
    return $result;
}

我认为可能会有潜在的问题www.example.com/myurl.html?
Earlee

1

因为我同时处理相对URL和绝对URL,所以我更新了veritas的解决方案,如下面的代码。
您可以在这里尝试一下:https : //ideone.com/PvpZ4J

function removeQueryStringFromUrl($url) {
    if (substr($url,0,4) == "http") {
        $urlPartsArray = parse_url($url);
        $outputUrl = $urlPartsArray['scheme'] . '://' . $urlPartsArray['host'] . ( isset($urlPartsArray['path']) ? $urlPartsArray['path'] : '' );
    } else {
        $URLexploded = explode("?", $url, 2);
        $outputUrl = $URLexploded[0];
    }
    return $outputUrl;
}

1

也可以根据PHP手册注释使用以下内容

$_SERVER['REDIRECT_URL']

请注意,这仅适用于某些PHP环境,请按照该页面的下面的注释获取更多信息;

目的:当前PHP文件的URL路径名称,path-info为N / A,不包括URL查询字符串。包括斜杠。

警告:这是在URL重写之前(即,按照原始调用URL)。

注意:并非在所有PHP环境中都设置,并且绝对只有在URL可重写的环境中才设置。

在网络模式下工作:是

在CLI模式下工作:否


0

试试这个

$url_with_querystring = 'www.mydomian.com/myurl.html?unwantedthngs';
$url_data = parse_url($url_with_querystring);
$url_without_querystring = str_replace('?'.$url_data['query'], '', $url_with_querystring);

0

假设您仍然希望获取不带查询args的URL(如果未设置),只需使用简写的if语句来检查strpos

$request_uri = strpos( $_SERVER['REQUEST_URI'], '?' ) !== false ? strtok( $_SERVER["REQUEST_URI"], '?' ) : $_SERVER['REQUEST_URI'];

0

如果您使用Laravel,这是一个简单的解决方案:

Str::before($request->getRequestUri(), '?')

-3

试试这个:

$urrl=$_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME']

要么

$urrl=$_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']

1
抱歉,这是错误的-可以用htaccess重写URI-这将导致返回脚本名称,而不是当前URI。
Hexodus '16

危险,可能会被欺骗。
蒂姆(Tim)2013年

确认是错误的。假设您正在编写proxy.php,它是.htaccess重定向到对各种资源(例如index.php,prices.php,about.php)的请求,并动态构建所请求名称的视图。如果使用此选项,脚本将始终显示proxy.php而不是它想要构建的所需请求资源。
德米特里(Dmitry)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.