Jak usunąć kwerendę i uzyskać tylko adres URL?

201

Używam PHP do zbudowania adresu URL bieżącej strony. Czasami adresy URL w postaci

www.mydomian.com/myurl.html?unwantedthngs

są wymagane. Chcę usunąć ?i wszystko, co następuje po nim (kwerenda), tak aby wynikowy adres URL stał się:

www.mydomain.com/myurl.html

Mój obecny kod to:

<?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;
}
?>
Navi Gamage
źródło
8
BTW, to się nazywa „ciąg zapytania”.
Evan Mulawski,

Odpowiedzi:

577

Możesz użyć, strtokaby uzyskać ciąg przed pierwszym wystąpieniem?

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

strtok()reprezentuje najbardziej zwięzłą technikę bezpośredniego wyciągania podłańcucha przed ?kwerendą. explode()jest mniej bezpośredni, ponieważ musi wytworzyć potencjalnie dwuelementową tablicę, za pomocą której należy uzyskać dostęp do pierwszego elementu.

Niektóre inne techniki mogą się zepsuć, gdy brakuje kwerendy lub potencjalnie mutować inne / niezamierzone podciągi w adresie URL - technik tych należy unikać.

demonstracja :

$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";
}

Wynik:

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
)
---
RiaD
źródło
24
+1 za bezpośrednie użycie $ _SERVER zamiast odbudowywania adresu URL tylko w celu jego ponownej analizy. dałoby kolejne +1, jeśli to możliwe, do rozstrzygnięcia.
ericsoco
8
Ups - odwróć te argumenty dla explode (), separator jest pierwszy. array_shift(explode('?',$_SERVER["REQUEST_URI"]))
tutaj
13
Nie zwraca bool (fałsz) jeśli? nie jest obecny w ciągu, zwraca ciąg.
Ben C
4
Świetnie! .. Nadal zwraca adres URL, nawet jeśli ?nie jest obecny.
Harikrishnan
1
@sepehr, po prostu nie widzę sensu, aby nie używać funkcji, która robi dokładnie to, czego potrzebujesz, i używać innej i analizować wynik (tj. uzyskać [0] po wybuchu) (chyba że istnieje konkretny powód, taki jak lepsza wydajność , brak zbędnej zależności itp.).
RiaD,
66

Użyj PHP Manual - parse_url (), aby uzyskać potrzebne części.

Edytuj (przykładowe użycie @Navi Gamage)

Możesz użyć tego w następujący sposób:

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

    return $constructed_url;
}

?>

Edycja (drugi pełny przykład):

Zaktualizowana funkcja, aby upewnić się, że schemat zostanie dołączony i nie pojawią się żadne powiadomienia:

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));
}       

Wróci:

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
)

To jest wynik z przekazywania przykładowych adresów URL przez parse_url () bez drugiego parametru (tylko dla wyjaśnienia).

I to jest końcowy wynik po zbudowaniu adresu URL przy użyciu:

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

Wynik:

http://www.mydomian.com/myurl.html
http://www.mydomian.com/myurl.html
http://www.mydomian.com
https://mydomian.com/myurl.html
veritas
źródło
Przeczytałem to ... Jestem trochę zdezorientowany, ponieważ jeśli jesteś nowy w php. Czy możesz mi pomóc z powyższym kodem php?
Navi Gamage,
dodałem ten kod po wierszu 9 $ pageURL = substr ($ pageURL, 0, strrpos ($ pageURL, „?”));
Navi Gamage
Czyści sekcję zapytania w adresie URL ...> www.mydomain.com/myurl.html?unwantedthings wynik jest OK! > www.mydomian.com/myurl.html Gotowe ... Ale jeśli chodzi o normalny adres URL> www.mydomain.com/myurl.html wynik jest niczym .. Puste
Navi Gamage
strrpos () w 'www.mydomain.com/myurl.html' zwróci 0 (FAŁSZ rzutowany na wartość logiczną, aby być bardziej poprawnym), więc twój substr będzie pusty. Użyj one : substr () LUB parse_url (), ponieważ użycie obu nie ma sensu;)
veritas
Miałem na myśli FALSE casted do int; D
veritas
54

najlepsze rozwiązanie:

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

Jeśli przesyłasz formularz do tej samej domeny, nie musisz dołączać do niego swojej http://domain.com .

Ludo - Nieoficjalnie
źródło
Pamiętaj, że parse_url oczekuje bezwzględnego adresu URL, więc w niektórych przypadkach otrzymasz nieprawidłowe wyniki, np. Jeśli REQUEST_URL zaczyna się od wielu kolejnych ukośników. Będą one interpretowane jako URI zależne od protokołu.
NikiC,
16
$val = substr( $url, 0, strrpos( $url, "?"));
zellio
źródło
Faceci zgodnie z twoimi odpowiedziami Gotowe .. dziękuję za pomoc .. Czyści sekcję zapytania w adresie URL ...
Navi Gamage
> www.mydomain.com/myurl.html?unwantedthings wynik jest OK! > www.mydomian.com/myurl.html Gotowe ... Ale jeśli chodzi o zwykły adres URL> www.mydomain.com/myurl.html wynik jest niczym .. Puste
Navi Gamage
Nowy kod php code <? Funkcja php 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”]; $ pageURL = substr ($ pageURL, 0, strrpos ($ pageURL, „?”)); } return $ pageURL; }?>code
Navi Gamage,
2
Myślę, że jest to raczej słodkie i proste rozwiązanie problemu. Nie potrzeba mnóstwa rozszerzeń ani funkcji. Użyłem tego, aby uzyskać bieżącą nazwę pliku. $ base = basename ($ _ SERVER ['REQUEST_URI']); $ page = substr ($ base, 0, strrpos ($ base, "?"));
Rob
Jak stwierdził Navi, ta odpowiedź nie jest wiarygodna. 3v4l.org/nhVii Jeśli kwerenda nie występuje w adresie URL, cały adres URL jest usuwany! Ta technika nie rozpoznaje składników adresu URL. Ta odpowiedź jest niewskazana.
mickmackusa
9

Najłatwiejszy sposób

$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
Mukesh Saxena
źródło
Nie zgadzam się, że jest to najłatwiejsza droga. Nie, pogrubiony tekst nie zwiększa atrakcyjności Twojego oświadczenia. W tej odpowiedzi nie ma wyjaśnienia.
mickmackusa
@mickmackusa Czy mógłbyś rozwinąć swój komentarz? Gdzie muszę wyjaśnić swoją odpowiedź? Będę ci wdzięczny.
Mukesh Saxena
Wszystkie odpowiedzi na Stackoverflow powinny zawierać wyjaśnienie, jak działa rozwiązanie i dlaczego uważasz, że jest to idealna technika. Linki do dokumentacji są również mile widziane. W pełni rozumiem twoje rozwiązanie, ale inny badacz może nie. Tylko kodowe odpowiedzi mają niewielką wartość w Stackoverflow, ponieważ niewiele robią, aby edukować / wspierać tysiące przyszłych badaczy. O tym, że nie jest najprostszy - 3v4l.org/RE0GD byłby prostszą wersją twojej odpowiedzi, ponieważ ma mniej zadeklarowanych zmiennych i powoduje tylko jedną zamianę zamiast dwóch. Akceptowana odpowiedź jest najprostsza ze wszystkich.
mickmackusa
Kolejna różnica polega na tym, że zaakceptowana odpowiedź zajmuje się również możliwym fragmentem, ale twój nie. 3v4l.org/ERr4V lub gorzej może to Magiel URL do lewej strony kwerendy 3v4l.org/L61q1
mickmackusa
4

Możesz użyć wbudowanej funkcji parse_url w następujący sposób:

$baseUrl = $_SERVER['SERVER_NAME'] . parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
Mohammad altenji
źródło
2

Możesz spróbować:

<?php
$this_page = basename($_SERVER['REQUEST_URI']);
if (strpos($this_page, "?") !== false) $this_page = reset(explode("?", $this_page));
?>
ysrb
źródło
2

Jeśli chcesz uzyskać ścieżkę zapytania ( więcej informacji ):

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

Jeśli chcesz usunąć zapytanie i (a może także fragment):

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);
użytkownik1079877
źródło
1

Aby usunąć ciąg zapytania z identyfikatora URI żądania, zastąp ciąg zapytania pustym ciągiem:

function request_uri_without_query() {
    $result = $_SERVER['REQUEST_URI'];
    $query = $_SERVER['QUERY_STRING'];
    if(!empty($query)) {
        $result = str_replace('?' . $query, '', $result);
    }
    return $result;
}
Ryan Prechel
źródło
Myślę, że byłby to potencjalny problem www.example.com/myurl.html?.
Earlee
1

Ponieważ mam do czynienia zarówno z względnymi, jak i bezwzględnymi adresami URL, zaktualizowałem rozwiązanie Veritas, takie jak poniższy kod.
Możesz spróbować tutaj: 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;
}
trante
źródło
1

może również użyć następujących zgodnie z komentarzem ręcznym php

$_SERVER['REDIRECT_URL']

Pamiętaj, że działa to tylko w niektórych środowiskach PHP i postępuj zgodnie z poniższym komentarzem z tej strony, aby uzyskać więcej informacji;

Cel: Nazwa ścieżki URL bieżącego pliku PHP, ścieżka-info to N / D, z wyłączeniem ciągu zapytania URL. Obejmuje wiodący ukośnik.

Zastrzeżenie: jest to przed przepisaniem adresu URL (tzn. Zgodnie z pierwotnym adresem URL połączenia).

Zastrzeżenie: Nie ustawione we wszystkich środowiskach PHP, a na pewno tylko w tych z przepisem adresów URL.

Działa w trybie internetowym: Tak

Działa w trybie CLI: Nie

Janith Chinthana
źródło
0

Spróbuj tego

$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);
kwelsan
źródło
0

Zakładając, że nadal chcesz uzyskać adres URL bez argumentów zapytania (jeśli nie są ustawione), po prostu użyj skróconej instrukcji if, aby sprawdzić za pomocą strpos:

$request_uri = strpos( $_SERVER['REQUEST_URI'], '?' ) !== false ? strtok( $_SERVER["REQUEST_URI"], '?' ) : $_SERVER['REQUEST_URI'];
sMyles
źródło
0

Oto proste rozwiązanie, jeśli używasz Laravel:

Str::before($request->getRequestUri(), '?')
ahinkle
źródło
-3

Spróbuj tego:

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

lub

$urrl=$_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']
HRALDA
źródło
1
Przykro nam, ale to źle - identyfikator URI może zostać przepisany przez htaccess - spowoduje to zwrócenie nazwy skryptu, ale nie bieżący identyfikator URI.
Heksodus
Niebezpieczne, ponieważ może być sfałszowane.
tim
potwierdź, że jest źle. Załóżmy, że piszesz proxy.php, który jest .htaccess przekierowuje z żądań różnych zasobów, takich jak index.php, prices.php, about.php, i dynamicznie buduje widok dla żądanej nazwy. jeśli go użyjesz, skrypt zawsze zobaczy proxy.php zamiast żądanego zasobu, który chce zbudować.
Dmitry