在PHP中获取完整的URL

我使用此代码获取完整的URL:

$actual_link = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];

问题是我在.htaccess中使用了一些掩码,所以我们在URL中看到的并不总是文件的真实路径。

我需要的是获取URL,URL中写的内容,不多也不少-完整的URL。

我需要了解它在Web浏览器的导航栏中的显示方式,而不是服务器上文件的真实路径。

3718547 次浏览

看看$_SERVER['REQUEST_URI'],即。

$actual_link = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

(注意双引号字符串语法是完全正确

如果您想同时支持HTTP和HTTPS,可以使用

$actual_link = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

使用此代码的编者注:具有安全影响。客户端可以将HTTP_HOST和REQUEST_URI设置为它想要的任何值。

这对您的Apache环境变量很容易做到。这只适用于Apache 2,我假设您正在使用它。

只需使用以下PHP代码:

<?php$request_url = apache_getenv("HTTP_HOST") . apache_getenv("REQUEST_URI");echo $request_url;?>

在网页上输出链接的简短版本

$url =  "//{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
$escaped_url = htmlspecialchars( $url, ENT_QUOTES, 'UTF-8' );echo '<a href="' . $escaped_url . '">' . $escaped_url . '</a>';

以下是关于//example.com/path/格式的问题和边缘情况的更多细节

完整版

function url_origin( $s, $use_forwarded_host = false ){$ssl      = ( ! empty( $s['HTTPS'] ) && $s['HTTPS'] == 'on' );$sp       = strtolower( $s['SERVER_PROTOCOL'] );$protocol = substr( $sp, 0, strpos( $sp, '/' ) ) . ( ( $ssl ) ? 's' : '' );$port     = $s['SERVER_PORT'];$port     = ( ( ! $ssl && $port=='80' ) || ( $ssl && $port=='443' ) ) ? '' : ':'.$port;$host     = ( $use_forwarded_host && isset( $s['HTTP_X_FORWARDED_HOST'] ) ) ? $s['HTTP_X_FORWARDED_HOST'] : ( isset( $s['HTTP_HOST'] ) ? $s['HTTP_HOST'] : null );$host     = isset( $host ) ? $host : $s['SERVER_NAME'] . $port;return $protocol . '://' . $host;}
function full_url( $s, $use_forwarded_host = false ){return url_origin( $s, $use_forwarded_host ) . $s['REQUEST_URI'];}
$absolute_url = full_url( $_SERVER );echo $absolute_url;

这是http://snipplr.com/view.php?codeview&;id=2734的严重修改版本(已不存在)

URL结构:

方案://用户名:密码@domain:端口/路径?query_string#fragment_id

粗体部分不会包含在函数中

备注:

  • 此函数不包括来自完整URL或片段(哈希)的username:password
  • 它不会显示HTTP的默认端口80和HTTPS的默认端口443。
  • 仅使用超文本传输协议和https方案进行测试。
  • #fragment_id不会被客户端(浏览器)发送到服务器,也不会被添加到完整的URL中。
  • 对于像/example?foo=bar1&foo=bar2这样的URL,$_GET只会包含foo=bar2
  • 一些CMS和环境将重写$_SERVER['REQUEST_URI']并返回/example?foo=bar2以获取像/example?foo=bar1&foo=bar2这样的URL,在这种情况下使用$_SERVER['QUERY_STRING']
  • 请记住,URI=URL + URN,但由于流行使用,URL现在意味着URI和URL。
  • 如果您不打算使用代理或平衡器,则应删除HTTP_X_FORWARDED_HOST
  • 规格表示Host标头必须包含端口号,除非它是默认编号。

客户端(浏览器)控制的变量:

  • $_SERVER['REQUEST_URI'].任何不受支持的字符在发送之前都会被浏览器编码。
  • $_SERVER['HTTP_HOST']并且根据PHP手册中的注释并不总是可用:http://php.net/manual/en/reserved.variables.php
  • $_SERVER['HTTP_X_FORWARDED_HOST']由平衡器设置,在PHP手册的$_SERVER变量列表中没有提到。

服务器控制的变量:

  • $_SERVER['HTTPS']。客户端选择使用它,但服务器返回实际值为空或“on”。
  • $_SERVER['SERVER_PORT'].服务器只接受允许的数字作为端口。
  • $_SERVER['SERVER_PROTOCOL'].服务器只接受某些协议。
  • $_SERVER['SERVER_NAME']。它是在服务器配置中手动设置的,根据kralyk不适用于IPv6。

相关:

PHP中HTTP_HOST和SERVER_NAME有什么区别?
HTTP“Host”标头参数中是否需要端口号?
https://stackoverflow.com/a/28049503/175071

这是一个使用三元语句的解决方案,保持代码最小:

$url = "http" . (($_SERVER['SERVER_PORT'] == 443) ? "s" : "") . "://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

这是最小且最简单的方法,假设您的Web服务器使用HTTPS的标准端口443。

function full_path(){$s = &$_SERVER;$ssl = (!empty($s['HTTPS']) && $s['HTTPS'] == 'on') ? true:false;$sp = strtolower($s['SERVER_PROTOCOL']);$protocol = substr($sp, 0, strpos($sp, '/')) . (($ssl) ? 's' : '');$port = $s['SERVER_PORT'];$port = ((!$ssl && $port=='80') || ($ssl && $port=='443')) ? '' : ':'.$port;$host = isset($s['HTTP_X_FORWARDED_HOST']) ? $s['HTTP_X_FORWARDED_HOST'] : (isset($s['HTTP_HOST']) ? $s['HTTP_HOST'] : null);$host = isset($host) ? $host : $s['SERVER_NAME'] . $port;$uri = $protocol . '://' . $host . $s['REQUEST_URI'];$segments = explode('?', $uri, 2);$url = $segments[0];return $url;}

注意:我刚刚对Timo Huovinen的密码进行了更新,因此您不会在URL中获得任何GET参数。此URL是普通的,并删除了?hi=i&am=a&get之类的内容。

示例:

http://www.example.com/index?get=information

将显示为:

http://www.example.com/index

这很好,除非你使用GET参数来定义一些特定的内容,在这种情况下,你应该使用他的代码!:-)

这是我的解决方案-代码受到特雷西调试器的启发。它被更改以支持不同的服务器端口。您可以获得包括$_SERVER['REQUEST_URI']或基本服务器URL的完整当前URL。检查我的功能:

function getCurrentUrl($full = true) {if (isset($_SERVER['REQUEST_URI'])) {$parse = parse_url((isset($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'off') ? 'https://' : 'http://') .(isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '')) . (($full) ? $_SERVER['REQUEST_URI'] : null));$parse['port'] = $_SERVER["SERVER_PORT"]; // Setup protocol for sure (80 is default)return http_build_url('', $parse);}}

下面是测试代码:

// Follow $_SERVER variables was set only for test$_SERVER['HTTPS'] = 'off'; // on$_SERVER['SERVER_PORT'] = '9999'; // Setup$_SERVER['HTTP_HOST'] = 'some.crazy.server.5.name:8088'; // Port is optional there$_SERVER['REQUEST_URI'] = '/150/tail/single/normal?get=param';
echo getCurrentUrl();// http://some.crazy.server.5.name:9999/150/tail/single/normal?get=param
echo getCurrentUrl(false);// http://some.crazy.server.5.name:9999/

这是您问题的解决方案:

//Fetch page URL by this
$url = $_SERVER['REQUEST_URI'];echo "$url<br />";
//It will print//fetch host by this
$host=$_SERVER['HTTP_HOST'];echo "$host<br />";
//You can fetch the full URL by this
$fullurl = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];echo $fullurl;

试试这个:

print_r($_SERVER);

$_SERVER是一个包含标头、路径和脚本位置等信息的数组。此数组中的条目由Web服务器创建。不能保证每个Web服务器都会提供其中的任何一个;服务器可能会省略一些,或者提供此处未列出的其他变量。也就是说,“CGI/1.1规范中包含了大量这些变量,所以你应该可以期待这些。

$HTTP_SERVER_VARS包含相同的初始信息,但不是超全局的。(请注意,$HTTP_SERVER_VARS$_SERVER是不同的变量,PHP将它们作为不同的变量处理)

我最喜欢的跨平台查找当前URL的方法是:

$url = (isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

我创建了这个函数来处理URL:

 <?phpfunction 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;}?>

与接受的答案相同的技术,但支持HTTPS,并且更具可读性:

$current_url = sprintf('%s://%s/%s',isset($_SERVER['HTTPS']) ? 'https' : 'http',$_SERVER['HTTP_HOST'],$_SERVER['REQUEST_URI']);

上面给出了不需要的斜杠。在我的设置Request_URI上有前导斜杠和尾随斜杠。这对我来说更好。

$Current_Url = sprintf('%s://%s/%s',isset($_SERVER['HTTPS']) ? 'https' : 'http',$_SERVER['HTTP_HOST'],trim($_SERVER['REQUEST_URI'],'/\\'));

示例:https://(www.)example.com/subFolder/myfile.php?var=blabla#555

// ======= PATHINFO ====== //$x = pathinfo($url);$x['dirname']      🡺 https://example.com/subFolder$x['basename']     🡺                               myfile.php?var=blabla#555 // Unsecure!$x['extension']    🡺                                      php?var=blabla#555 // Unsecure!$x['filename']     🡺                               myfile
// ======= PARSE_URL ====== //$x = parse_url($url);$x['scheme']       🡺 https$x['host']         🡺         example.com$x['path']         🡺                    /subFolder/myfile.php$x['query']        🡺                                          var=blabla$x['fragment']     🡺                                                     555
//=================================================== ////========== Self-defined SERVER variables ========== ////=================================================== //$_SERVER["DOCUMENT_ROOT"]  🡺 /home/user/public_html$_SERVER["SERVER_ADDR"]    🡺 143.34.112.23$_SERVER["SERVER_PORT"]    🡺 80 (or 443, etc..)$_SERVER["REQUEST_SCHEME"] 🡺 https                                         //similar: $_SERVER["SERVER_PROTOCOL"]$_SERVER['HTTP_HOST']      🡺         example.com (or with WWW)             //similar: $_SERVER["SERVER_NAME"]$_SERVER["REQUEST_URI"]    🡺                       /subFolder/myfile.php?var=blabla$_SERVER["QUERY_STRING"]   🡺                                             var=blabla__FILE__                   🡺 /home/user/public_html/subFolder/myfile.php__DIR__                    🡺 /home/user/public_html/subFolder              //same: dirname(__FILE__)$_SERVER["REQUEST_URI"]    🡺                       /subFolder/myfile.php?var=blablaparse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH)🡺  /subFolder/myfile.php$_SERVER["PHP_SELF"]       🡺                       /subFolder/myfile.php
// ==================================================================////if "myfile.php" is included in "PARENTFILE.php" , and you visit  "PARENTFILE.PHP?abc":$_SERVER["SCRIPT_FILENAME"]🡺 /home/user/public_html/parentfile.php$_SERVER["PHP_SELF"]       🡺                       /parentfile.php$_SERVER["REQUEST_URI"]    🡺                       /parentfile.php?var=blabla__FILE__                   🡺 /home/user/public_html/subFolder/myfile.php
// =================================================== //// ================= handy variables ================= //// =================================================== //// If the site uses HTTPS:$HTTP_or_HTTPS = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS']!=='off') || $_SERVER['SERVER_PORT']==443) ? 'https://':'http://' );            //in some cases, you need to add this condition too: if ('https'==$_SERVER['HTTP_X_FORWARDED_PROTO'])  ...
// To trim values to filename, i.e.basename($url)             🡺 myfile.php
// Excellent solution to find origin$debug_files = debug_backtrace();$caller_file = count($debug_files) ? $debug_files[count($debug_files) - 1]['file'] : __FILE__;

注意!

  • 主题标签#部分在上面的示例中手动使用,只是为了说明目的,但是,服务器端语言(包括PHP)无法原生检测它们(只有JavaScript可以做到这一点,因为主题标签只有浏览器/客户端功能)。
  • 对于Windows类型的主机,DIRECTORY_SEPARATOR返回\,而不是/

____

对于WordPress

// (Let's say, if WordPress is installed in subdirectory:  http://example.com/wpdir/)home_url()                      🡺 http://example.com/wpdir/        // If is_ssl() is true, then it will be "https"get_stylesheet_directory_uri()  🡺 http://example.com/wpdir/wp-content/themes/THEME_NAME  [same: get_bloginfo('template_url') ]get_stylesheet_directory()      🡺 /home/user/public_html/wpdir/wp-content/themes/THEME_NAMEplugin_dir_url(__FILE__)        🡺 http://example.com/wpdir/wp-content/themes/PLUGIN_NAMEplugin_dir_path(__FILE__)       🡺 /home/user/public_html/wpdir/wp-content/plugins/PLUGIN_NAME/

您可以使用不带参数的http_build_url来获取当前页面的完整url

$url = http_build_url();

用途:

$base_dir = __DIR__; // Absolute path to your installation, ex: /var/www/mywebsite$doc_root = preg_replace("!{$_SERVER['SCRIPT_NAME']}$!", '', $_SERVER['SCRIPT_FILENAME']); # ex: /var/www$base_url = preg_replace("!^{$doc_root}!", '', $base_dir); # ex: '' or '/mywebsite'$base_url = str_replace('\\', '/', $base_url);//On Windows$base_url = str_replace($doc_root, '', $base_url);//On Windows$protocol = empty($_SERVER['HTTPS']) ? 'http' : 'https';$port = $_SERVER['SERVER_PORT'];$disp_port = ($protocol == 'http' && $port == 80 || $protocol == 'https' && $port == 443) ? '' : ":$port";$domain = $_SERVER['SERVER_NAME'];$full_url = "$protocol://{$domain}{$disp_port}{$base_url}"; # Ex: 'http://example.com', 'https://example.com/mywebsite', etc.

来源:PHP文档根,路径和URL检测

使用此单行代码查找父文件夹URL(如果您无法访问pecl_http附带的http_build_url()):

$url = (isset($_SERVER['HTTPS']) ? 'https://' : 'http://').$_SERVER['SERVER_NAME'].str_replace($_SERVER['DOCUMENT_ROOT'], '', dirname(dirname(__FILE__)));

我用了这个声明。

$base = "http://$_SERVER[SERVER_NAME]:$_SERVER[SERVER_PORT]$my_web_base_path";$url = $base . "/" . dirname(dirname(__FILE__));

我觉得这个方法不错,试试看

if($_SERVER['HTTP_HOST'] == "localhost"){define('SITEURL', 'http://' . $_SERVER['HTTP_HOST']);define('SITEPATH', $_SERVER['DOCUMENT_ROOT']);define('CSS', $_SERVER['DOCUMENT_ROOT'] . '/css/');define('IMAGES', $_SERVER['DOCUMENT_ROOT'] . '/images/');}else{define('SITEURL', 'http://' . $_SERVER['HTTP_HOST']);define('SITEPATH', $_SERVER['DOCUMENT_ROOT']);define('TEMPLATE', $_SERVER['DOCUMENT_ROOT'] . '/incs/template/');define('CSS', $_SERVER['DOCUMENT_ROOT'] . '/css/');define('IMAGES', $_SERVER['DOCUMENT_ROOT'] . '/images/');}

只需使用:

$uri = $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']

清晰的代码,适用于所有Web服务器(Apache、nginx、IIS…):

$url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

这适用于HTTP和HTTPS。

echo 'http' . (($_SERVER['HTTPS'] == 'on') ? 's' : '') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

输出这样的东西。

https://example.com/user.php?token=3f0d9sickc0flmg8hnsngk5u07&;access_level=应用

我使用了下面的代码,它对我来说工作正常,对于HTTP和HTTPS。

function curPageURL() {if(isset($_SERVER["HTTPS"]) && !empty($_SERVER["HTTPS"]) && ($_SERVER["HTTPS"] != 'on' )) {$url = 'https://'.$_SERVER["SERVER_NAME"];//https url}  else {$url =  'http://'.$_SERVER["SERVER_NAME"];//http url}if(( $_SERVER["SERVER_PORT"] != 80 )) {$url .= $_SERVER["SERVER_PORT"];}$url .= $_SERVER["REQUEST_URI"];return $url;}
echo curPageURL();

演示

您可以使用HTTP_ORIGIN,如下面的片段所示:

if ( ! array_key_exists( 'HTTP_ORIGIN', $_SERVER ) ) {$this->referer = $_SERVER['SERVER_NAME'];} else {$this->referer = $_SERVER['HTTP_ORIGIN'];}
$page_url = (isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

更多:如何使用PHP获取页面的完整URL

非常简单的使用:

function current_url() {$current_url  = ( $_SERVER["HTTPS"] != 'on' ) ? 'http://'.$_SERVER["SERVER_NAME"] :  'https://'.$_SERVER["SERVER_NAME"];$current_url .= ( $_SERVER["SERVER_PORT"] != 80 ) ? ":".$_SERVER["SERVER_PORT"] : "";$current_url .= $_SERVER["REQUEST_URI"];
return $current_url;}

以下是一个更安全的已接受答案版本的基础,使用PHP的filter_input函数,这也弥补了$_SERVER['REQUEST_URI']的潜在不足:

$protocol_https = filter_input(INPUT_SERVER, 'HTTPS', FILTER_SANITIZE_STRING);$host = filter_input(INPUT_SERVER, 'HTTP_HOST', FILTER_SANITIZE_URL);$request_uri = filter_input(INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_URL);if(strlen($request_uri) == 0){$request_uri = filter_input(INPUT_SERVER, 'SCRIPT_NAME', FILTER_SANITIZE_URL);$query_string = filter_input(INPUT_SERVER, 'QUERY_STRING', FILTER_SANITIZE_URL);if($query_string){$request_uri .= '?' . $query_string;}}$full_url = ($protocol_https ? 'https' : 'http') . '://' . $host . $request_uri;

你可以使用一些不同的过滤器来调整它。

HTTP_HOST和REQUEST_URI必须在引号中,否则在PHP 7.2中抛出错误

用途:

$actual_link = 'https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];

如果您想同时支持HTTP和HTTPS:

$actual_link = (isset($_SERVER['HTTPS']) ? 'https' : 'http').'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
    public static function getCurrentUrl($withQuery = true){$protocol = (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off')or (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https')or (!empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off')or (isset($_SERVER['SERVER_PORT']) && intval($_SERVER['SERVER_PORT']) === 443) ? 'https' : 'http';
$uri = $protocol . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
return $withQuery ? $uri : str_replace('?' . $_SERVER['QUERY_STRING'], '', $uri);}