Come rimuovere la stringa di query e ottenere solo l'URL?


201

Sto usando PHP per creare l'URL della pagina corrente. A volte, gli URL sotto forma di

www.mydomian.com/myurl.html?unwantedthngs

sono richiesti. Voglio rimuovere il ?e tutto ciò che lo segue (querystring), in modo che l'URL risultante diventi:

www.mydomain.com/myurl.html

Il mio codice attuale è questo:

<?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
A proposito, si chiama "stringa di query".
Evan Mulawski,

Risposte:


578

È possibile utilizzare strtokper ottenere la stringa prima della prima occorrenza di?

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

strtok()rappresenta la tecnica più concisa per estrarre direttamente la sottostringa prima della stringa ?di querystring. explode()è meno diretto perché deve produrre un array potenzialmente a due elementi mediante il quale è necessario accedere al primo elemento.

Alcune altre tecniche possono rompersi quando manca la stringa di querystring o potenzialmente mutare sottostringhe altre / non intenzionali nell'url - queste tecniche dovrebbero essere evitate.

Una dimostrazione :

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

Produzione:

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 per l'utilizzo diretto di $ _SERVER invece di ricostruire l'URL solo per analizzarlo di nuovo. darebbe un altro +1 se possibile, per concisione.
ericsoco,

8
Oops - inverte quegli argomenti per explode (), il delimitatore inizia per primo. array_shift(explode('?',$_SERVER["REQUEST_URI"]))
qui,

13
Non restituisce bool (falso) se? non è presente nella stringa, restituisce la stringa.
Ben C

4
Fantastico! .. Sta ancora restituendo l'URL anche se ?non è presente.
Harikrishnan,

1
@sepehr, non vedo alcun punto di non usare la funzione che fa esattamente ciò di cui hai bisogno e usarne un altro e analizzarne il risultato (cioè ottenere [0] dopo l'esplosione) (a meno che ovviamente non ci sia un motivo specifico come una migliore prestazione , mancanza di dipendenza non necessaria, ecc.).
RiaD

66

Utilizzare PHP Manuale - parse_url () per ottenere le parti necessarie.

Modifica (esempio di utilizzo per @Navi Gamage)

Puoi usarlo in questo modo:

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

    return $constructed_url;
}

?>

Modifica (secondo esempio completo):

Funzione aggiornata per assicurarsi che lo schema sia collegato e che non vengano visualizzati messaggi msg:

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

Sarà di ritorno:

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
)

Questo è l'output del passaggio degli URL di esempio attraverso parse_url () senza un secondo parametro (solo per spiegazione).

E questo è l'output finale dopo aver creato l'URL usando:

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

Produzione:

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

L'ho letto..Im un po 'confuso perché se non conoscete php. Potete aiutarmi con il codice php sopra?
Navi Gamage,

ho aggiunto questo codice dopo la riga 9 $ pageURL = substr ($ pageURL, 0, strrpos ($ pageURL, "?"));
Navi Gamage,

Pulisce la sezione delle query nell'URL ...> www.mydomain.com/myurl.html?unwantedthings il risultato è OK! > www.mydomian.com/myurl.html Fatto ... Ma quando si tratta di un normale url> www.mydomain.com/myurl.html il risultato non è niente .. Vuoto
Navi Gamage

strrpos () in "www.mydomain.com/myurl.html" restituirà 0 (FALSO trasmesso in booleano per essere più corretto) in modo che il tuo substr sia vuoto. Usa one : substr () O parse_url () perché usare entrambi non ha senso;)
veritas

Intendevo FALSO trasmesso a int; D
veritas il

54

soluzione migliore:

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

Non è necessario includere il tuo http://domain.com nel tuo se stai inviando un modulo allo stesso dominio.


Tieni presente che parse_url prevede un URL assoluto, quindi in alcuni casi otterrai risultati errati, ad esempio se REQUEST_URL inizia con più barre consecutive. Quelli saranno interpretati come un URI relativo al protocollo.
NikiC,

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

Ragazzi, cerco le vostre risposte. Ho finito ... grazie per il vostro aiuto. Pulisce la sezione delle domande nell'url ...
Navi Gamage,

> www.mydomain.com/myurl.html?unwantedthings il risultato è OK! > www.mydomian.com/myurl.html Fatto ... Ma quando si tratta di un normale url> www.mydomain.com/myurl.html il risultato non è niente .. Vuoto
Navi Gamage

Nuovo codice php code <? 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"]; $ pageURL = substr ($ pageURL, 0, strrpos ($ pageURL, "?")); } return $ pageURL; }?>code
Navi Gamage il

2
Penso che questa sia una soluzione piuttosto dolce e semplice al problema. Non sono necessarie molte estensioni o funzioni. Ho usato questo per ottenere l'attuale nome del file chiamato. $ base = basename ($ _ SERVER ['REQUEST_URI']); $ page = substr ($ base, 0, strrpos ($ base, "?"));
Rob,

Come affermato da Navi, questa risposta non è affidabile. 3v4l.org/nhVii Se la stringa di query è assente nell'URL , l'intero URL viene rimosso! Questa tecnica non è sensibile ai componenti dell'URL. Questa risposta è sconsigliata.
Mickmackusa,

9

Il modo più semplice

$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

Non sono d'accordo sul fatto che questo sia il modo più semplice. No, il testo in grassetto non rende la tua dichiarazione più convincente. A questa risposta manca una spiegazione.
Mickmackusa,

@mickmackusa Potresti per favore elaborare il tuo commento? Dove devo spiegare la mia risposta? Ti sarò grato.
Mukesh Saxena,

Tutte le risposte su StackOverflow dovrebbero includere una spiegazione di come funziona la soluzione e perché ritieni che sia una tecnica ideale. Sono inoltre benvenuti collegamenti alla documentazione. Comprendo appieno la tua soluzione, ma altri ricercatori potrebbero non esserlo. Le risposte di solo codice hanno un valore basso su StackOverflow perché fanno molto poco per educare / responsabilizzare migliaia di futuri ricercatori. Di non essere più semplice - 3v4l.org/RE0GD sarebbe una versione più semplice della tua risposta perché ha meno variabili dichiarate e fa solo una sostituzione invece di due. La risposta accettata è la più semplice di tutte.
Mickmackusa,

Un'altra differenza è che la risposta accettata si occupa anche di un possibile frammento, ma il tuo no. 3v4l.org/ERr4V o peggio potrebbe rovinare l'url a sinistra della querystring 3v4l.org/L61q1
mickmackusa,


4

Puoi usare la funzione build in parse_url in questo modo:

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

2

Puoi provare:

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

2

Se vuoi ottenere il percorso della richiesta ( maggiori informazioni ):

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

Se vuoi rimuovere la query e (e forse anche il frammento):

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

Per rimuovere la stringa di query dall'URI della richiesta, sostituire la stringa di query con una stringa vuota:

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

Penso che ci sarebbe un potenziale problema con www.example.com/myurl.html?.
Earlee il

1

Poiché mi occupo sia di URL relativi che assoluti, ho aggiornato la soluzione di Veritas come il codice seguente.
Puoi provarti qui: 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

potrebbe anche usare il seguito come da commento manuale php

$_SERVER['REDIRECT_URL']

Nota che funziona solo per determinati ambienti PHP e segui il seguente commento da quella pagina per maggiori informazioni;

Scopo: il nome percorso URL del file PHP corrente, informazioni percorso è N / D ed esclusa la stringa di query URL. Include barra iniziale.

Avvertenza: è prima della riscrittura dell'URL (ovvero è come per l'URL della chiamata originale).

Avvertenza: non impostato su tutti gli ambienti PHP e sicuramente solo quelli con riscrittura degli URL.

Funziona in modalità Web: Sì

Funziona in modalità CLI: No


0

Prova questo

$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

Supponendo che tu voglia ancora ottenere l'URL senza la query args (se non sono impostati), basta usare una scorciatoia se l'istruzione per verificare con strpos:

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

0

Ecco una soluzione semplice se si utilizza Laravel:

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

-3

Prova questo:

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

o

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

1
Ci dispiace ma questo è sbagliato - L'URI può essere riscritto da htaccess - questo comporterebbe la restituzione del nome dello script ma non dell'URI corrente.
Hexodus,

Pericoloso in quanto può essere falsificato.
tim

la conferma è sbagliata. supponiamo di scrivere proxy.php che è .htaccess reindirizza da richieste per varie risorse come index.php, prices.php, about.php e costruisce dinamicamente una vista per il nome richiesto. se lo usi, lo script vedrà sempre proxy.php anziché la risorsa richiesta desiderata che vuole costruire.
Dmitry,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.