Как удалить строку запроса и получить только URL?


201

Я использую PHP для создания URL текущей страницы. Иногда URL-адреса в виде

www.mydomian.com/myurl.html?unwantedthngs

запрашиваются. Я хочу удалить ?и все, что следует за ним (querystring), так что результирующий 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
Кстати, это называется «строка запроса».
Эван Мулавски

Ответы:


578

Вы можете использовать, 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, даже если ?его нет.
Харикришнан

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 результат - ничто .. Пусто
Navi Gamage

strrpos () в 'www.mydomain.com/myurl.html' вернет 0 (FALSE приведен к логическому значению, чтобы быть более правильным), так что ваш substr будет пустым. Используйте один : 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 ...
Navi Gamage

> www.mydomain.com/myurl.html?unwantedthings результат в порядке! > www.mydomian.com/myurl.html Готово ... Но когда оно приходит с нормальным URL-адресом> www.mydomain.com/myurl.html результат - ничто .. Пусто
Navi Gamage

Новый код 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

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

Как заявил Navi, этот ответ не является надежным. 3v4l.org/nhVii Если в URL отсутствует строка запроса, весь 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 слева от строки
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


4

Вы можете использовать встроенную функцию parse_url следующим образом:

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

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, path-info - N / A, исключая строку запроса URL. Включает ведущий слеш.

Предостережение: это перед перезаписью URL-адреса (то есть в соответствии с исходным URL-адресом вызова).

Предостережение: Не установлен во всех средах 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 без аргументов запроса (если они не заданы), просто используйте сокращение if для проверки 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.