PHPで完全なURLを取得する

2011年07月21日に質問されました。  ·  閲覧回数 3.1M回  ·  ソース

DiegoP. picture
2011年07月21日

私はこのコードを使用して完全なURLを取得します:

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

問題は、 .htaccessでいくつかのマスクを使用しているため、URLに表示されるのは必ずしもファイルの実際のパスではないということです。

私が必要としているのは、URL、URLに書かれているもの、それ以上でもそれ以下でもない完全なURLを取得することです。

サーバー上のファイルの実際のパスではなく、Webブラウザーのナビゲーションバーにどのように表示されるかを取得する必要があります。

回答

ax. picture
2011年07月21日
2147

$_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を任意の値に設定できます。

Timo Huovinen picture
2012年01月17日
430

ウェブページにリンクを出力するための短いバージョン

$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は表示されません。
  • httpおよびhttpsスキームでのみテストされています。
  • #fragment_idは、クライアント(ブラウザー)によってサーバーに送信されず、完全なURLに追加されません。
  • $_GETは、 /example?foo=bar1&foo=bar2ようなURLのfoo=bar2のみが含まれます。
  • いくつかのCMSのと環境がリライトします$_SERVER['REQUEST_URI']して返す/example?foo=bar2のようなURLのための/example?foo=bar1&foo=bar2 、使用$_SERVER['QUERY_STRING']このケースで。
  • URI = URL + URNであることに注意してください。ただし、一般的に使用されているため、URLはURIとURLの両方を意味するようになりました。
  • プロキシまたはバランサーを使用する予定がない場合は、 HTTP_X_FORWARDED_HOSTを削除する必要があります。
  • 仕様によると、 Hostヘッダーには、デフォルトの番号でない限り、ポート番号が含まれている必要があります。

クライアント(ブラウザー)制御変数:

  • $_SERVER['REQUEST_URI'] 。 サポートされていない文字は、送信される前にブラウザによってエンコードされます。
  • $_SERVER['HTTP_HOST']あり、PHPマニュアルのコメントによると常に利用できるとは限りません: http
  • $_SERVER['HTTP_X_FORWARDED_HOST']はバランサーによって設定され、PHPマニュアルの$_SERVER変数のリストには記載されていません。

サーバー制御変数:

  • $_SERVER['HTTPS'] 。 クライアントはこれを使用することを選択しますが、サーバーは空または「オン」の実際の値を返します。
  • $_SERVER['SERVER_PORT'] 。 サーバーは、許可された番号のみをポートとして受け入れます。
  • $_SERVER['SERVER_PROTOCOL'] 。 サーバーは特定のプロトコルのみを受け入れます。
  • $_SERVER['SERVER_NAME'] 。 サーバー構成で手動で設定され、 kralykによるとIPv6では使用できません。

関連:

HTTP_HOSTとSERVER_NAME
HTTP「ホスト」ヘッダーパラメータにポート番号は必要ですか?
https://stackoverflow.com/a/28049503/175071

T.Todua picture
2014年11月15日
236

例: 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["ERVER_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=blabla
parse_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 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のみが検出できます) browser/client side機能のみです)。
  • DIRECTORY_SEPARATORは、 /ではなく、Windowsタイプのホスティングの場合は\を返します。


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_NAME
plugin_dir_url(__FILE__)        🡺 http://example.com/wpdir/wp-content/themes/PLUGIN_NAME
plugin_dir_path(__FILE__)       🡺 /home/user/public_html/wpdir/wp-content/plugins/PLUGIN_NAME/  
honyovk picture
2012年04月24日
64

コードを最小限に抑えながら、 3項ステートメントを使用するソリューションを次に示します。

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

これは、WebサーバーがHTTPSに標準ポート443を使用していると仮定すると、これを行うための最小かつ最も簡単な方法です。

Daniel Gillespie picture
2014年05月18日
46

現在のURLを見つけるための私のお気に入りのクロスプラットフォームの方法は次のとおりです。

$url = (isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
HappyCoder picture
2015年12月09日
35

単に使用してください:

$uri = $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']
Alex Westergaard picture
2012年10月26日
22
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パラメータを使用して特定のコンテンツを定義しない限り、これは問題ありません。その場合は、彼のコードを使用する必要があります。 :-)

Andreas picture
2016年04月27日
19

すべてのWebサーバー(Apache、nginx、IISなど)で機能する明確なコード:

$url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
Kai Noack picture
2018年06月28日
14

HTTP_HOSTとREQUEST_URIは引用符で囲む必要があります。そうでない場合、PHP7.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'];
OzzyCzech picture
2013年08月07日
11

ここに私のソリューションです-コードが触発されトレイシーデバッガ。 さまざまなサーバーポートをサポートするために変更されました。 $_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/