Manipuluj ciągiem adresu URL, dodając parametry GET

93

Chcę dodać parametry GET do adresów URL, które mogą, ale nie muszą, zawierać parametry GET bez powtarzania ?lub &.

Przykład:

Jeśli chcę dodać category=action

$url="http://www.acme.com";
 // will add ?category=action at the end

$url="http://www.acme.com/movies?sort=popular";
 // will add &category=action at the end

Jeśli zauważysz, próbuję nie powtarzać znaku zapytania, jeśli zostanie znaleziony.

Adres URL to tylko ciąg.

Jaki jest niezawodny sposób dołączenia określonego parametru GET?

Ryan
źródło
Wystarczy użyć: echo http_build_url($url, array("query" => "the=query&parts=here"), HTTP_URL_JOIN_QUERY);. Ale będziesz potrzebować pecl install pecl_httplub zainstalować jakeasmith / http_build_url za pośrednictwem kompozytora.
Ema4rl

Odpowiedzi:

188

Metoda podstawowa

$query = parse_url($url, PHP_URL_QUERY);

// Returns a string if the URL has parameters or NULL if not
if ($query) {
    $url .= '&category=1';
} else {
    $url .= '?category=1';
}

Bardziej zaawansowany

$url = 'http://example.com/search?keyword=test&category=1&tags[]=fun&tags[]=great';

$url_parts = parse_url($url);
// If URL doesn't have a query string.
if (isset($url_parts['query'])) { // Avoid 'Undefined index: query'
    parse_str($url_parts['query'], $params);
} else {
    $params = array();
}

$params['category'] = 2;     // Overwrite if exists
$params['tags'][] = 'cool';  // Allows multiple values

// Note that this will url_encode all values
$url_parts['query'] = http_build_query($params);

// If you have pecl_http
echo http_build_url($url_parts);

// If not
echo $url_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path'] . '?' . $url_parts['query'];

Powinieneś umieścić to przynajmniej w funkcji, jeśli nie w klasie.

andrewtweber
źródło
2
nie zapomnij też o dodaniu wartości kategorii
Doug T.
4
@DougT. nie wszystkie parametry wymagają podania wartości. Na przykład ?logoutmożna to sprawdzić za pomocąisset($_GET["logout"])
rybo111
Takie podejście jest dobre, gdy wiesz, że parametr „kategoria” nie znajduje się jeszcze w adresie URL. Jeśli parametr znajduje się już w adresie URL, to PHP powinien przyjąć wartość ostatniego wystąpienia parametru w adresie URL, więc rozwiązanie @andrewtweber nadal działa. Jednak bardziej podoba mi się następujące rozwiązanie stackoverflow.com/a/4101638/99256 .
Martin Vseticka,
-1 za niezastępowanie parametru, jeśli już istnieje. Nie jest to wyraźnie wymienione w pytaniu, ale jest logicznie i semantycznie obowiązkowe.
Daniel W.
1
Wystarczy użyć: echo http_build_url($url, array("query" => "the=query&parts=here"), HTTP_URL_JOIN_QUERY);. Ale będziesz potrzebować pecl install pecl_httplub zainstalować jakeasmith / http_build_url za pośrednictwem kompozytora.
Ema4rl
55

Oto krótsza wersja zaakceptowanej odpowiedzi:

$url .= (parse_url($url, PHP_URL_QUERY) ? '&' : '?') . 'category=action';

Edycja: jak omówiono w zaakceptowanej odpowiedzi, jest to błąd polegający na tym, że nie sprawdza, czy categoryjuż istnieje. Lepszym rozwiązaniem byłoby potraktowanie $_GETtego, czym jest - tablicą - i użycie takich funkcji in_array().

rybo111
źródło
Zauważ, że zadziała to tylko z jednym dodanym parametrem, w przeciwnym razie doda? jeśli nie było pierwotnego zapytania.
Mgamerz
@Mgamerz, chyba że źle cię rozumiem, o to poprosił OP. Działa wielokrotnie, ponieważ .przed =.
rybo111
Ale zapytanie nie będzie istnieć, jeśli dodasz parametr do adresu URL (stąd dodasz?), A jeśli zrobisz to ponownie, doda kolejny? (Chyba że masz ponownie uruchomić pierwszą linię)? Jak aktualizuje się $ query?
Mgamerz
@Mgamerz Teraz rozumiem, co masz na myśli. Tak, za każdym razem musiałbyś powtarzać pierwszą linię, aby sprawdzić, czy $urlma już parametry. Edytowano.
rybo111
1
Nie obsługuje adresów URL z rozszerzeniem #.
NateS
19
$data = array('foo'=>'bar',
              'baz'=>'boom',
              'cow'=>'milk',
              'php'=>'hypertext processor');

$queryString =  http_build_query($data);
//$queryString = foo=bar&baz=boom&cow=milk&php=hypertext+processor

echo 'http://domain.com?'.$queryString;
//output: http://domain.com?foo=bar&baz=boom&cow=milk&php=hypertext+processor
Tom Claus
źródło
Wystarczy użyć: echo http_build_url($url, array("query" => "the=query&parts=here"), HTTP_URL_JOIN_QUERY);. Ale będziesz potrzebować pecl install pecl_httplub zainstalować jakeasmith / http_build_url za pośrednictwem kompozytora.
Ema4rl
8

Użyj strpos, aby wykryć?. Od ? może pojawić się tylko w adresie URL na początku ciągu zapytania, wiesz, czy jego parametry już istnieją i musisz dodać parametry za pomocą &

function addGetParamToUrl(&$url, $varName, $value)
{
    // is there already an ?
    if (strpos($url, "?"))
    {
        $url .= "&" . $varName . "=" . $value; 
    }
    else
    {
        $url .= "?" . $varName . "=" . $value;
    }
}
Doug T.
źródło
Dobre i łatwe podejście, jeśli obawiasz się o wydajność, ponieważ będzie to znacznie szybsze niż parse_url, a także mniej obciążające procesor. Kompromisem jest to, że nie sprawdza istniejącej zmiennej $ varName.
Dennis Stücken
8

Ta funkcja zastępuje istniejący argument

function addToURL( $key, $value, $url) {
    $info = parse_url( $url );
    parse_str( $info['query'], $query );
    return $info['scheme'] . '://' . $info['host'] . $info['path'] . '?' . http_build_query( $query ? array_merge( $query, array($key => $value ) ) : array( $key => $value ) );
}
user2171027
źródło
Co się stanie, jeśli nie ma $info['query']zestawu? Nie uwzględniłeś tego.
Darren
Jeśli nie jest ustawione, $ info ['query'] przyjmuje wartość NULL, a $ query staje się pustą tablicą. Więc to nie jest problem.
Ajay Singh,
7

Przykład z aktualizacją istniejących parametrów.

Użyto również url_encode i możliwość nie określania wartości parametru

    <?
    /**
     * Add parameter to URL
     * @param string $url
     * @param string $key
     * @param string $value
     * @return string result URL
     */
    function addToUrl($url, $key, $value = null) {
        $query = parse_url($url, PHP_URL_QUERY);
        if ($query) {
            parse_str($query, $queryParams);
            $queryParams[$key] = $value;
            $url = str_replace("?$query", '?' . http_build_query($queryParams), $url);
        } else {
            $url .= '?' . urlencode($key) . '=' . urlencode($value);
        }
        return $url;
    }
Артур Курицын
źródło
5
<?php
$url1 = '/test?a=4&b=3';
$url2 = 'www.baidu.com/test?a=4&b=3&try_count=1';
$url3 = 'http://www.baidu.com/test?a=4&b=3&try_count=2';
$url4 = '/test';
function add_or_update_params($url,$key,$value){
    $a = parse_url($url);
    $query = $a['query'] ? $a['query'] : '';
    parse_str($query,$params);
    $params[$key] = $value;
    $query = http_build_query($params);
    $result = '';
    if($a['scheme']){
        $result .= $a['scheme'] . ':';
    }
    if($a['host']){
        $result .= '//' . $a['host'];
    }
    if($a['path']){
        $result .=  $a['path'];
    }
    if($query){
        $result .=  '?' . $query;
    }
    return $result;
}
echo add_or_update_params($url1,'try_count',1);
echo "\n";
echo add_or_update_params($url2,'try_count',2);
echo "\n";
echo add_or_update_params($url3,'try_count',3);
echo "\n";
echo add_or_update_params($url4,'try_count',4);
echo "\n";
shengbin_xu
źródło
3
świetna robota, tylko zamień linię $query = $a['query'] ? $a['query'] : '';na$query = isset($a['query']) ? $a['query'] : '';
emmgfx
4
 /**
 * @example addParamToUrl('/path/to/?find=1', array('find' => array('search', 2), 'FILTER' => 'STATUS'))
 * @example addParamToUrl('//example.com/path/to/?find=1', array('find' => array('search', 2), 'FILTER' => 'STATUS'))
 * @example addParamToUrl('https://example.com/path/to/?find=1&FILTER=Y', array('find' => array('search', 2), 'FILTER' => 'STATUS'))
 *
 * @param       $url string url
 * @param array $addParams
 *
 * @return string
 */
function addParamToUrl($url, array $addParams) {
  if (!is_array($addParams)) {
    return $url;
  }

  $info = parse_url($url);

  $query = array();

  if ($info['query']) {
    parse_str($info['query'], $query);
  }

  if (!is_array($query)) {
    $query = array();
  }

  $params = array_merge($query, $addParams);

  $result = '';

  if ($info['scheme']) {
    $result .= $info['scheme'] . ':';
  }

  if ($info['host']) {
    $result .= '//' . $info['host'];
  }

  if ($info['path']) {
    $result .= $info['path'];
  }

  if ($params) {
    $result .= '?' . http_build_query($params);
  }

  return $result;
}
Londeren
źródło
3
$parameters = array();

foreach ($get as $key => $value)
{
     $parameters[] = $key.'='.$value;
}

$url = 'http://example.com/movies?'.implode('&', $parameters);
TaylorOtwell
źródło
3

Myślę, że powinieneś to zrobić coś takiego.

class myURL {
    protected $baseURL, $requestParameters;

    public function __construct ($newURL) {
        $this->baseurl = $newURL;
        $this->requestParameters = array();
    }

    public function addParameter ($parameter) {
        $this->requestParameters[] = $parameter;
    }

    public function __toString () {
        return $this->baseurl.
               ( count($this->requestParameters) ?
                 '?'.implode('&', $this->requestParameters) :
                 ''
                 );
    }
}

$url1 = new myURL ('http://www.acme.com');
$url2 = new myURL ('http://www.acme.com');
$url2->addParameter('sort=popular');
$url2->addParameter('category=action');
$url1->addParameter('category=action');

echo $url1."\n".$url2;
Hammerite
źródło
1

Po wyszukaniu wielu zasobów / odpowiedzi na ten temat postanowiłem zakodować własne. W oparciu o odpowiedź @ TaylorOtwell tutaj, w ten sposób przetwarzam przychodzące żądanie $ _GET i modyfikuję / manipuluję każdym elementem.

Zakładając, że adres URL to: http://domain.com/category/page.php?a=b&x=y I chcę mieć tylko jeden parametr do sortowania: albo? Desc = nazwa_kolumny lub? Asc = nazwa_kolumny. W ten sposób pojedynczy parametr adresu URL wystarczy do jednoczesnego sortowania i porządkowania. Tak więc adres URL będzie http://domain.com/category/page.php?a=b&x=y&desc=column_name po pierwszym kliknięciu powiązanego wiersza nagłówka tabeli.

Następnie mam nagłówki wierszy tabeli, które chcę posortować DESC przy pierwszym kliknięciu, a ASC przy drugim kliknięciu tego samego nagłówka. (Każde pierwsze kliknięcie powinno być najpierw „ORDER BY kolumny DESC”). Jeśli nie ma sortowania, będzie ono domyślnie sortowane według „daty i identyfikatora”.

Możesz go jeszcze bardziej ulepszyć, na przykład dodać funkcje czyszczenia / filtrowania do każdego komponentu $ _GET, ale poniższa struktura stanowi podstawę.

foreach ($_GET AS $KEY => $VALUE){
    if ($KEY == 'desc'){
        $SORT = $VALUE;
        $ORDER = "ORDER BY $VALUE DESC";
        $URL_ORDER = $URL_ORDER . "&asc=$VALUE";
    } elseif ($KEY == 'asc'){
        $SORT = $VALUE;
        $ORDER = "ORDER BY $VALUE ASC";
        $URL_ORDER = $URL_ORDER . "&desc=$VALUE";
    } else {
        $URL_ORDER .= "&$KEY=$VALUE";
        $URL .= "&$KEY=$VALUE";
    }
}
if (!$ORDER){$ORDER = 'ORDER BY date DESC, id DESC';}
if ($URL_ORDER){$URL_ORDER = $_SERVER[SCRIPT_URL] . '?' . trim($URL_ORDER, '&');}
if ($URL){$URL = $_SERVER[SCRIPT_URL] . '?' . trim($URL, '&');}

(Możesz użyć $ _SERVER [SCRIPT_URI] dla pełnego adresu URL zaczynającego się od http://domain.com )

Następnie używam otrzymanego powyżej zamówienia $ ORDER w zapytaniu MySQL:

"SELECT * FROM table WHERE limiter = 'any' $ORDER";

Teraz funkcja, która sprawdza adres URL, jeśli istnieje poprzednie sortowanie i dodaje parametr sortowania (i porządkowania) do adresu URL z "?" lub „&” zgodnie z sekwencją:

        function sort_order ($_SORT){
            global $SORT, $URL_ORDER, $URL;
            if ($SORT == $_SORT){
                return $URL_ORDER;
            } else {
                if (strpos($URL, '?') !== false){
                    return "$URL&desc=$_SORT";
                } else {                        
                    return "$URL?desc=$_SORT";
                }
            }
        }

Na koniec nagłówek wiersza tabeli do użycia funkcji:

        echo "<th><a href='".sort_order('id')."'>ID</a></th>";

Podsumowanie: spowoduje to odczytanie adresu URL, zmodyfikowanie każdego z komponentów $ _GET i utworzenie końcowego adresu URL z wybranymi przez Ciebie parametrami z poprawną formą użycia znaku „?” i "&"

Tarik
źródło
0
 public function addGetParamToUrl($url, $params)
{
    foreach ($params as $param) {
         if (strpos($url, "?"))
        {
            $url .= "&" .http_build_query($param); 
        }
        else
        {
            $url .= "?" .http_build_query($param); 
        }
    }
    return $url;
}
Maor Kavod
źródło
0

kolejna ulepszona wersja funkcji. Połączenie istniejących odpowiedzi z niewielkimi ulepszeniami (obsługa portów) i poprawkami błędów (prawidłowe sprawdzanie kluczy).

/**
 * @param string $url original url to modify - can be relative, partial etc
 * @param array $paramsOverride associative array, can be empty
 * @return string modified url
 */
protected function overrideUrlQueryParams($url, $paramsOverride){
    if (!is_array($paramsOverride)){
        return $url;
    }

    $url_parts = parse_url($url);

    if (isset($url_parts['query'])) {
        parse_str($url_parts['query'], $params);
    } else {
        $params = [];
    }

    $params = array_merge($params, $paramsOverride);

    $res = '';

    if(isset($url_parts['scheme'])) {
        $res .= $url_parts['scheme'] . ':';
    }

    if(isset($url_parts['host'])) {
        $res .= '//' . $url_parts['host'];
    }

    if(isset($url_parts['port'])) {
        $res .= ':' . $url_parts['port'];
    }

    if (isset($url_parts['path'])) {
        $res .= $url_parts['path'];
    }

    if (count($params) > 0) {
        $res .= '?' . http_build_query($params);
    }

    return $res;
}
Roman86
źródło
0

Wypróbuj tę funkcję, aby dodać parametry adresu URL .

Następnie możesz wyłączyć łącze, gdy parametr jest ustawiony, aby nie było duplikatu parametru adresu URL.

<?php
  function addQueryString($a)
                {
             if (empty($_SERVER['QUERY_STRING']))
               return '?' . $a;
             else if (!empty($_SERVER['QUERY_STRING']))
              return '?' . $_SERVER['QUERY_STRING'] . '&' . $a;
                }
?>

 <a href="<?php echo addQueryString('lang=en'); ?>">test</a>
 <a href="<?php echo addQueryString('category=5'); ?>">sat</a>
csandreas1
źródło