ฉันจะรับ URL เต็มของหน้าปัจจุบันบนเซิร์ฟเวอร์ Windows / IIS ได้อย่างไร


137

ฉันย้ายการติดตั้งWordPressไปยังโฟลเดอร์ใหม่บนเซิร์ฟเวอร์Windows / IIS ฉันตั้งค่าการเปลี่ยนเส้นทาง 301 ใน PHP แต่ดูเหมือนจะไม่ทำงาน URL โพสต์ของฉันมีรูปแบบดังต่อไปนี้:

http:://www.example.com/OLD_FOLDER/index.php/post-title/

ฉันไม่สามารถหาวิธีจับ/post-title/ส่วนของ URL ได้

$_SERVER["REQUEST_URI"]- ซึ่งทุกคนดูเหมือนว่าจะแนะนำ - กำลังคืนสตริงว่าง เป็นเพียงการกลับมา$_SERVER["PHP_SELF"] index.phpเหตุใดจึงเป็นเช่นนี้และฉันจะแก้ไขได้อย่างไร


24
เพียงแค่ทำการ print_r ($ _ SERVER) และดูว่ามีข้อมูลใดบ้างที่คุณสามารถใช้ได้ หากคุณสามารถรับ URL แบบเต็มคุณสามารถโทรหา pathinfo ($ url) เพื่อรับชื่อไฟล์
gradbot

18
ควรสังเกตว่าคำถามนี้เกี่ยวกับ IIS ไม่ใช่ PHP โดยทั่วไป ใน Apache คุณเพียงแค่ใช้ $ _SERVER ['REQUEST_URI']
Michał Tatarynowicz

@Pies แน่นอน $ _SERVER ['REQUEST_URI'] เป็นวิธีที่จะไป ... แต่ฉันจะคว้าส่วนเฉพาะของ URI ได้อย่างไรตัวอย่างเช่นฉันมี URI นี้: /Appointments/Administrator/events.php/219 ... ฉันจะคว้าหมายเลขได้อย่างไรหลังจาก /events.php/
Dimitris Papageorgiou

ซ้ำเป็นไปได้ของรับ URL แบบเต็มใน PHP
T.Todua

คำตอบ:


135

อาจเป็นเพราะคุณอยู่ภายใต้ IIS

$_SERVER['PATH_INFO']

คือสิ่งที่คุณต้องการตาม URL ที่คุณใช้อธิบาย

สำหรับ Apache $_SERVER['REQUEST_URI']คุณต้องการใช้


สวัสดีโดยใช้มันฉันเพิ่งได้รับข้อผิดพลาดดังต่อไปนี้? Notice: Undefined index: PATH_INFO in /home/tdpk/public_html/system/config.php on line 14
chhameed

6
อ๊ะ drat - เพิ่งรู้ว่าคำถามนี้เกี่ยวกับ IIS และฉันใช้ ขออภัยสำหรับ downvote
Jason S

63
$pageURL = (@$_SERVER["HTTPS"] == "on") ? "https://" : "http://";
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;

11
OP ระบุไว้อย่างชัดเจน IIS - REQUEST_URI ไม่สามารถใช้งานได้ภายใต้ IIS
Tom Auger

1
คุณไม่ควรใช้ magicquotes เว้นแต่ว่าคุณจะต้องเป็น php
คดี

2
@TomAuger คุณต้องดูไทม์ไลน์ OP เพิ่มนานนี้หลังจากที่ฉันตอบคำถาม คำถามเดิมถูกถามประมาณหนึ่งปีก่อนที่ฉันจะตอบ
Tyler Carter

7
@Stan ไม่มีประโยชน์สุทธิต่อประสิทธิภาพการใช้ซิงเกิ้ลมากกว่าคู่ ไม่มี, nadda, zip, ศูนย์ มันเป็นเรื่องเล่าเก่าแก่ของยุค PHP3 โปรดอย่าทำเรื่องยุ่งเหยิงในเนื้อหา
ชาร์ลส์

36

สำหรับ Apache:

'http'.(empty($_SERVER['HTTPS'])?'':'s').'://'.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI']


คุณสามารถใช้HTTP_HOSTแทนการSERVER_NAMEแสดงความคิดเห็นของเฮอร์แมนได้ ดูคำถามที่เกี่ยวข้องนี้สำหรับการสนทนาแบบเต็ม ในระยะสั้นคุณอาจตกลงกับการใช้อย่างใดอย่างหนึ่ง นี่คือรุ่น 'โฮสต์':

'http'.(empty($_SERVER['HTTPS'])?'':'s').'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']


สำหรับ Paranoid / Why it Matters

โดยทั่วไปแล้วฉันตั้งค่าServerNameในVirtualHostเพราะฉันต้องการที่จะเป็นรูปแบบบัญญัติของเว็บไซต์ $_SERVER['HTTP_HOST']เป็นที่ตั้งอยู่บนพื้นฐานของส่วนหัวของการร้องขอ หากเซิร์ฟเวอร์ตอบสนองต่อชื่อโดเมนใด ๆ / ทั้งหมดที่อยู่ IP นั้นผู้ใช้สามารถหลอกส่วนหัวหรือแย่กว่านั้นบางคนสามารถชี้ระเบียน DNS ไปยังที่อยู่ IP ของคุณจากนั้นเซิร์ฟเวอร์ / เว็บไซต์ของคุณจะแสดงผลเว็บไซต์ด้วยไดนามิก ลิงก์ที่สร้างด้วย URL ที่ไม่ถูกต้อง หากคุณใช้วิธีหลังคุณควรกำหนดค่าvhostหรือตั้งค่า.htaccessกฎเพื่อบังคับใช้โดเมนที่คุณต้องการให้บริการเช่น:

RewriteEngine On
RewriteCond %{HTTP_HOST} !(^stackoverflow.com*)$
RewriteRule (.*) https://stackoverflow.com/$1 [R=301,L]
#sometimes u may need to omit this slash ^ depending on your server

หวังว่าจะช่วย จุดที่แท้จริงของคำตอบนี้ก็เพื่อให้บรรทัดแรกของรหัสสำหรับคนที่ลงเอยที่นี่เมื่อค้นหาวิธีที่จะได้รับ URL ที่สมบูรณ์ด้วย apache :)


2
นี้ควรจะใช้แทน$_SERVER['HTTP_HOST'] $_SERVER['SERVER_NAME']หากมีการตั้งค่าโฮสต์เสมือน SERVER_NAME จะแสดงชื่อนั้น อาจเป็นสิ่ง*.example.comที่ไม่ถูกต้อง
Herman J. Radtke III


9

ใช้คลาสนี้เพื่อให้ URL ใช้งานได้

class VirtualDirectory
{
    var $protocol;
    var $site;
    var $thisfile;
    var $real_directories;
    var $num_of_real_directories;
    var $virtual_directories = array();
    var $num_of_virtual_directories = array();
    var $baseURL;
    var $thisURL;

    function VirtualDirectory()
    {
        $this->protocol = $_SERVER['HTTPS'] == 'on' ? 'https' : 'http';
        $this->site = $this->protocol . '://' . $_SERVER['HTTP_HOST'];
        $this->thisfile = basename($_SERVER['SCRIPT_FILENAME']);
        $this->real_directories = $this->cleanUp(explode("/", str_replace($this->thisfile, "", $_SERVER['PHP_SELF'])));
        $this->num_of_real_directories = count($this->real_directories);
        $this->virtual_directories = array_diff($this->cleanUp(explode("/", str_replace($this->thisfile, "", $_SERVER['REQUEST_URI']))),$this->real_directories);
        $this->num_of_virtual_directories = count($this->virtual_directories);
        $this->baseURL = $this->site . "/" . implode("/", $this->real_directories) . "/";
        $this->thisURL = $this->baseURL . implode("/", $this->virtual_directories) . "/";
    }

    function cleanUp($array)
    {
        $cleaned_array = array();
        foreach($array as $key => $value)
        {
            $qpos = strpos($value, "?");
            if($qpos !== false)
            {
                break;
            }
            if($key != "" && $value != "")
            {
                $cleaned_array[] = $value;
            }
        }
        return $cleaned_array;
    }
}

$virdir = new VirtualDirectory();
echo $virdir->thisURL;

10
นี่มันช่างเกินความจริงหรือเปล่า?
s3v3n

7

เพิ่ม:

function my_url(){
    $url = (!empty($_SERVER['HTTPS'])) ?
               "https://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] :
               "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
    echo $url;
}

จากนั้นเพียงเรียกใช้my_urlฟังก์ชัน


5

ฉันใช้ฟังก์ชันต่อไปนี้เพื่อรับ URL เต็มปัจจุบัน สิ่งนี้ควรใช้กับ IIS และ Apache

function get_current_url() {

  $protocol = 'http';
  if ($_SERVER['SERVER_PORT'] == 443 || (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on')) {
    $protocol .= 's';
    $protocol_port = $_SERVER['SERVER_PORT'];
  } else {
    $protocol_port = 80;
  }

  $host = $_SERVER['HTTP_HOST'];
  $port = $_SERVER['SERVER_PORT'];
  $request = $_SERVER['PHP_SELF'];
  $query = isset($_SERVER['argv']) ? substr($_SERVER['argv'][0], strpos($_SERVER['argv'][0], ';') + 1) : '';

  $toret = $protocol . '://' . $host . ($port == $protocol_port ? '' : ':' . $port) . $request . (empty($query) ? '' : '?' . $query);

  return $toret;
}

argv จะไม่ทำงานหากคุณไม่ได้ใช้ Apache หรือ IIS ที่ใช้ CGI ฉันลองใช้รหัสของคุณด้านบนบน Apache2 ในโหมดปกติ (ไม่ใช่โหมด CGI) และเกิดข้อผิดพลาดเนื่องจาก $ _SERVER ['arv'] [0] ไม่ใช่ดัชนี โปรดทราบว่าฉันเปิดรายงานข้อผิดพลาด PHP แบบเต็มและข้อผิดพลาดเหล่านี้เป็นข้อผิดพลาดแจ้งให้ทราบล่วงหน้า
Volomike

ทำงานเหมือนเสน่ห์เพียงแค่ต้องการให้มีการปรับปรุงเล็ก ๆ น้อย ๆ $query = isset($_SERVER['argv']) ? substr($_SERVER['argv'][0], strpos($_SERVER['argv'][0], ';') + 1) : '';เพื่อป้องกันข้อผิดพลาดในพารามิเตอร์สตริงแบบสอบถาม: ฉันได้อัปเดตคำตอบของคุณเพื่อรวมสิ่งนี้แล้ว
Zuul

4

REQUEST_URI ตั้งโดย Apache ดังนั้นคุณจะไม่ได้รับพร้อมกับ IIS ลองทำ var_dump หรือ print_r บน $ _SERVER และดูว่ามีค่าใดบ้างที่คุณสามารถใช้ได้


3

ส่วนหลังของURLคือหลังจากindex.phpไฟล์ของคุณซึ่งเป็นวิธีทั่วไปในการจัดทำ URL ที่จำง่ายโดยไม่ต้องใช้ mod_rewrite โพสต์คำบรรยายเป็นส่วนหนึ่งของสตริงข้อความค้นหาดังนั้นคุณควรจะได้รับมันโดยใช้ $ _SERVER ['QUERY_STRING']


2

ใช้บรรทัดต่อไปนี้ด้านบนของหน้าของ PHP $_SERVER['REQUEST_URI']ที่คุณกำลังใช้ นี่จะช่วยแก้ปัญหาของคุณ

$_SERVER['REQUEST_URI'] = $_SERVER['PHP_SELF'] . '?' . $_SERVER['argv'][0];

1

โอ้ความสนุกของตัวอย่าง!

if (!function_exists('base_url')) {
    function base_url($atRoot=FALSE, $atCore=FALSE, $parse=FALSE){
        if (isset($_SERVER['HTTP_HOST'])) {
            $http = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off' ? 'https' : 'http';
            $hostname = $_SERVER['HTTP_HOST'];
            $dir =  str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']);

            $core = preg_split('@/@', str_replace($_SERVER['DOCUMENT_ROOT'], '', realpath(dirname(__FILE__))), NULL, PREG_SPLIT_NO_EMPTY);
            $core = $core[0];

            $tmplt = $atRoot ? ($atCore ? "%s://%s/%s/" : "%s://%s/") : ($atCore ? "%s://%s/%s/" : "%s://%s%s");
            $end = $atRoot ? ($atCore ? $core : $hostname) : ($atCore ? $core : $dir);
            $base_url = sprintf( $tmplt, $http, $hostname, $end );
        }
        else $base_url = 'http://localhost/';

        if ($parse) {
            $base_url = parse_url($base_url);
            if (isset($base_url['path'])) if ($base_url['path'] == '/') $base_url['path'] = '';
        }

        return $base_url;
    }
}

มันมีผลตอบแทนที่สวยงามเช่น:

// A URL like http://stackoverflow.com/questions/189113/how-do-i-get-current-page-full-url-in-php-on-a-windows-iis-server:

echo base_url();    // Will produce something like: http://stackoverflow.com/questions/189113/
echo base_url(TRUE);    // Will produce something like: http://stackoverflow.com/
echo base_url(TRUE, TRUE); || echo base_url(NULL, TRUE); //Will produce something like: http://stackoverflow.com/questions/

// And finally:
echo base_url(NULL, NULL, TRUE);
// Will produce something like:
//      array(3) {
//          ["scheme"]=>
//          string(4) "http"
//          ["host"]=>
//          string(12) "stackoverflow.com"
//          ["path"]=>
//          string(35) "/questions/189113/"
//      }

0

ทุกคนลืมhttp_build_url ?

http_build_url($_SERVER['REQUEST_URI']);

เมื่อไม่มีการส่งพารามิเตอร์ไปให้http_build_urlจะถือว่า URL ปัจจุบันโดยอัตโนมัติ ฉันคาดหวังว่าREQUEST_URIจะรวมไว้ด้วยเช่นกันถึงแม้ว่ามันจะเป็นสิ่งที่จำเป็นเพื่อรวมพารามิเตอร์ GET

ตัวอย่างด้านบนจะส่งคืน URL แบบเต็ม


1
สิ่งนี้ต้องใช้ pecl_http
โอมาร์ Abid

@ OmarAbid ฉันแนะนำ :-)
Gajus

ฉันเข้าใจตำแหน่งของคุณ แต่เมื่อสร้างสคริปต์ที่จะใช้ในแพลตฟอร์มต่างๆที่คุณไม่สามารถควบคุมได้คุณต้องเลือกสิ่งที่ค่อนข้างมาตรฐาน
Omar Abid

1
หากคุณกำลังสร้างห้องสมุดมันขึ้นอยู่กับคุณที่จะกำหนดข้อกำหนด คำถามเดิมไม่ได้กล่าวถึงสถานการณ์ดังกล่าวเลย ดังนั้นจึงเหมาะสมที่จะตั้งชื่อตัวเลือกทั้งหมด
Gajus

0

ฉันใช้รหัสต่อไปนี้และฉันได้รับผลลัพธ์ที่ถูกต้อง ...

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

มันใช้งานได้ดีถ้าคุณไม่มี HTTPS คุณต้องลบมันออก

0

ในเซิร์ฟเวอร์ apache ของฉันนี่ให้ URL เต็มในรูปแบบที่แน่นอนที่คุณกำลังมองหา:

$_SERVER["SCRIPT_URI"]

0

สนับสนุนพร็อกซีย้อนกลับ!

บางสิ่งที่แข็งแกร่งกว่านี้เล็กน้อย หมายเหตุมันจะทำงานใน5.3หรือมากกว่าเท่านั้น

/*
 * Compatibility with multiple host headers.
 * Support of "Reverse Proxy" configurations.
 *
 * Michael Jett <mjett@mitre.org>
 */

function base_url() {

    $protocol = @$_SERVER['HTTP_X_FORWARDED_PROTO'] 
              ?: @$_SERVER['REQUEST_SCHEME']
              ?: ((isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") ? "https" : "http");

    $port = @intval($_SERVER['HTTP_X_FORWARDED_PORT'])
          ?: @intval($_SERVER["SERVER_PORT"])
          ?: (($protocol === 'https') ? 443 : 80);

    $host = @explode(":", $_SERVER['HTTP_HOST'])[0]
          ?: @$_SERVER['SERVER_NAME']
          ?: @$_SERVER['SERVER_ADDR'];

    // Don't include port if it's 80 or 443 and the protocol matches
    $port = ($protocol === 'https' && $port === 443) || ($protocol === 'http' && $port === 80) ? '' : ':' . $port;

    return sprintf('%s://%s%s/%s', $protocol, $host, $port, @trim(reset(explode("?", $_SERVER['REQUEST_URI'])), '/'));
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.