Як видалити рядок запитів і отримати лише URL-адресу?


201

Я використовую PHP для створення URL-адреси поточної сторінки. Іноді URL-адреси у вигляді

www.mydomian.com/myurl.html?unwantedthngs

запитуються. Я хочу видалити ?і все, що слідує за ним (рядок запитів), таким чином, що отримана URL-адреса стає:

www.mydomain.com/myurl.html

Мій поточний код такий:

<?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
BTW, це називається "рядок запиту".
Еван Мулавський

Відповіді:


577

Ви можете використовувати strtokрядок до першого появи?

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

strtok()представляє найбільш стислий прийом прямого витягування підрядки перед ?запитом у рядку запиту. explode()є менш прямим, оскільки він повинен створювати потенційно двоелементний масив, за допомогою якого повинен бути доступний перший елемент.

Деякі інші методи можуть порушитися, коли запит відсутній або потенційно мутує інші / ненавмисні підрядки в URL-адресі - цих методів слід уникати.

демонстрація :

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

Вихід:

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 за використання $ _SERVER безпосередньо замість того, щоб відновити URL лише для того, щоб знову його розібрати. дали би ще +1, якщо можливо, для стиснення.
ericsoco

8
На жаль, поверніть ці аргументи для explode (), роздільник переходить на перше місце. array_shift(explode('?',$_SERVER["REQUEST_URI"]))
тут

13
Якщо він не повертає bool (false), якщо? немає у рядку, він повертає рядок.
Бен С

4
Чудово! .. Це все ще повертає URL-адресу, навіть якщо ?її немає.
Harikrishnan

1
@sepehr, я просто не бачу сенсу не використовувати функцію, яка виконує саме те, що вам потрібно, і використовувати іншу та проаналізувати її результат (тобто отримати [0] після вибуху) (якщо, звичайно, немає конкретної причини, як краща продуктивність , відсутність зайвої залежності тощо).
RiaD

66

Використовуйте керівництво PHP - parse_url (), щоб отримати потрібні вам деталі.

Редагувати (приклад використання для @Navi Gamage)

Ви можете використовувати його так:

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

    return $constructed_url;
}

?>

Редагувати (другий повний приклад):

Оновлена ​​функція, щоб переконатися, що схема буде приєднана, і жодних повідомлень про повідомлення не з’явиться:

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

Повернеться:

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
)

Це вихід з перехідних прикладних URL-адрес через parse_url () без другого параметра (лише для пояснення).

Це завершальний результат після побудови URL-адреси, використовуючи:

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

Вихід:

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

Я читав це ... Я трохи заплутався, якщо новачок у php.Ви можете допомогти мені з вищезазначеним PHP-кодом?
Navi Gamage

я додав цей код після рядка 9 $ pageURL = substr ($ pageURL, 0, strrpos ($ pageURL, "?"));
Navi Gamage

Він очищає розділ запитів у URL-адресі ...> www.mydomain.com/myurl.html?unwantedthings результат: Добре! > www.mydomian.com/myurl.html Виконано ... Але коли мова йде про звичайну URL-адресу> www.mydomain.com/myurl.html результат - це нічого.
Порожнє

strrpos () у 'www.mydomain.com/myurl.html' поверне 0 (FALSE, який передано в булеве значення, щоб бути більш правильним), тому ваш субстр буде порожнім. Використовуйте одне : substr () АБО parse_url (), тому що використовувати обидва немає сенсу;)
veritas

Я мав на увазі ФАЛЬСЬКЕ заклинання до int; D
veritas

54

найкраще рішення:

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

Не потрібно включати http://domain.com у свій, якщо ви надсилаєте форму в той же домен.


Зауважте, що parse_url очікує абсолютну URL-адресу, тому ви отримаєте неправильні результати в деяких випадках, наприклад, якщо ваш REQUEST_URL починається з декількох послідовних косих косих. Вони трактуються як URI, що стосується протоколу.
NikiC

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

Хлопці, що підкоряються вашим відповідям. Я готовий ... Дякую за вашу допомогу. Він очищає розділ запитів у URL-
адресі

> www.mydomain.com/myurl.html?unwantedthings результат Гаразд! > www.mydomian.com/myurl.html Виконано ... Але коли мова йде про звичайну URL-адресу> www.mydomain.com/myurl.html результат - це нічого.
Порожнє

Новий php код code <? 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, "?")); } повернути $ pageURL; }?>code
Navi Gamage

2
Я думаю, що це досить солодке і просте рішення проблеми. Немає необхідності в навантаженні розтяжок або функцій. Я використовував це для отримання поточного названого файлу. $ base = базове ім'я ($ _ SERVER ['REQUEST_URI']); $ page = substr ($ base, 0, strrpos ($ base, "?"));
Роб

Як зазначає Navi, ця відповідь не є достовірною. 3v4l.org/nhVii Якщо запит в рядку відсутній, вся URL-адреса видаляється! Ця методика не відома URL-компонентів. Ця відповідь недоцільна.
mickmackusa

9

Найпростіший спосіб

$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

Я не згоден, що це найпростіший спосіб. Ні, жирний текст не робить вашу заяву більш переконливою. У цій відповіді відсутні пояснення.
mickmackusa

@mickmackusa Чи можете ви, будь ласка, розробити свій коментар? Де мені потрібно пояснити свою відповідь? Я буду вам вдячний
Мукеш Саксена

Усі відповіді на Stackoverflow повинні містити пояснення того, як працює рішення і чому ви вважаєте, що це ідеальна методика. Посилання на документацію також вітаються. Я повністю розумію ваше рішення, але інший дослідник може цього не робити. Відповіді, що стосуються лише коду, мають низьку цінність для Stackoverflow, оскільки вони роблять дуже мало для навчання / розширення можливостей тисяч майбутніх дослідників. Про те, щоб не бути найпростішим - 3v4l.org/RE0GD була б простішою версією вашої відповіді, оскільки вона має менше оголошених змінних і робить лише одну заміну замість двох. Прийнята відповідь найпростіша з усіх.
mickmackusa

Ще одна відмінність полягає в тому, що прийнята відповідь також піклується про можливий фрагмент, але ваш не буде. 3v4l.org/ERr4V або ще гірше, він міг би переплутати URL ліворуч від запиту 3v4l.org/L61q1
mickmackusa

7

Вам знадобиться принаймні PHP версії 5.4, щоб реалізувати це рішення, не вибухаючи в змінну на одній лінії та об'єднуючись на наступній, але легким одним вкладишем було б:

$_SERVER["HTTP_HOST"].explode('?', $_SERVER["REQUEST_URI"], 2)[0];

Змінні сервери: http://php.net/manual/en/reserved.variables.server.php
Перенаправлення масиву: https://wiki.php.net/rfc/functionarraydereferencing



2

Ви можете спробувати:

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

2

Якщо ви хочете отримати шлях запиту ( детальніше ):

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

Якщо ви хочете видалити запит і (а може бути, також фрагмент):

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

Щоб видалити рядок запиту з URI запиту, замініть рядок запиту порожнім рядком:

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

Я думаю, що з цим виникне потенційна проблема www.example.com/myurl.html?.
Ерлі

1

Оскільки я маю справу з відносними та абсолютними URL-адресами, я оновив рішення veritas, як наведений нижче код.
Ви можете спробувати тут: 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

може також використовувати наступне, як зазначено в коментарі до php-документа

$_SERVER['REDIRECT_URL']

Зверніть увагу, що це працює лише для певного середовища PHP, а для отримання додаткової інформації дотримуйтесь наведених нижче коментарів на цій сторінці;

Призначення: Назва шляху URL-адреси поточного файлу PHP, інформація про шлях становить N / A і виключаючи рядок запиту URL-адреси. Включає провідну косу рису.

Caveat: Це перед перезаписом URL-адреси (тобто, відповідно до оригінальної URL-адреси виклику).

Caveat: Не встановлено у всіх середовищах PHP, і, безумовно, лише в тих, що переписують URL.

Працює в веб-режимі: Так

Працює в режимі CLI: Ні


0

Спробуйте це

$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

Якщо припустити, що ви все ще хочете отримати URL-адресу без аргументів запиту (якщо вони не встановлені), просто скористайтеся скороченням, якщо заяву потрібно перевірити за допомогою strpos:

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

0

Ось просте рішення, якщо ви використовуєте Laravel:

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

-3

Спробуйте це:

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

або

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

1
Вибачте, але це неправильно - URI може бути переписаний htaccess - це призведе до повернення імені сценарію, але не поточного URI.
Гексод

Небезпечно, як це можна сфабрикувати.
час

підтвердити неправильно. припустимо, ви пишете proxy.php, який перенаправляє .htaccess з запитів на різні ресурси, такі як index.php, prices.php, about.php, і динамічно створює подання для запитуваного імені. якщо ви використовуєте це, сценарій завжди буде бачити proxy.php, а не потрібний запитуваний ресурс, який він хоче створити.
Дмитро
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.