Manipuler une chaîne d'URL en ajoutant des paramètres GET

93

Je souhaite ajouter des paramètres GET aux URL qui peuvent ou non contenir des paramètres GET sans répéter ?ou &.

Exemple:

Si je veux ajouter 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

Si vous remarquez que j'essaie de ne pas répéter le point d'interrogation s'il est trouvé.

L'URL n'est qu'une chaîne.

Quel est un moyen fiable d'ajouter un paramètre GET spécifique?

Ryan
la source
Il suffit d' utiliser: echo http_build_url($url, array("query" => "the=query&parts=here"), HTTP_URL_JOIN_QUERY);. Mais vous aurez besoin pecl install pecl_httpou installez jakeasmith / http_build_url via composer.
Ema4rl

Réponses:

188

Méthode de base

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

Plus avancé

$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'];

Vous devriez au moins mettre cela dans une fonction, sinon une classe.

andrewtweber
la source
2
n'oubliez pas non plus d'ajouter la valeur de la catégorie
Doug T.
4
@DougT. tous les paramètres n'ont pas besoin d'une valeur. Par exemple, ?logoutpeut être vérifié avecisset($_GET["logout"])
rybo111
Cette approche est bonne lorsque vous savez que le paramètre «category» n'est pas déjà dans l'URL. Si le paramètre est déjà dans une URL, PHP devrait prendre la valeur de la dernière occurrence du paramètre dans l'URL, donc la solution de @andrewtweber fonctionne toujours. Pourtant, j'aime mieux la solution suivante stackoverflow.com/a/4101638/99256 .
Martin Vseticka
-1 pour ne pas remplacer un paramètre s'il existe déjà. Ce n'est pas explicitement mentionné dans la question, mais c'est logiquement et sémantiquement obligatoire.
Daniel W.
1
Il suffit d' utiliser: echo http_build_url($url, array("query" => "the=query&parts=here"), HTTP_URL_JOIN_QUERY);. Mais vous aurez besoin pecl install pecl_httpou installez jakeasmith / http_build_url via composer.
Ema4rl
55

Voici une version plus courte de la réponse acceptée:

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

Edit: comme indiqué dans la réponse acceptée, cela présente un défaut en ce sens qu'il ne vérifie pas s'il categoryexiste déjà. Une meilleure solution serait de traiter le $_GETpour ce qu'il est - un tableau - et d'utiliser des fonctions comme in_array().

rybo111
la source
Notez que cela ne fonctionnera qu'avec un seul paramètre ajouté, sinon il ajoutera un? s'il n'y avait pas de requête d'origine.
Mgamerz
@Mgamerz à moins que je ne vous comprenne mal, c'est ce que le PO a demandé. Cela fonctionne plusieurs fois, à cause de l' .avant =.
rybo111
Mais la requête n'existera pas si vous ajoutez un paramètre à l'url (d'où l'ajout d'un?), Et si vous le faites à nouveau, il en ajoutera un autre? (Sauf si vous êtes censé exécuter à nouveau la première ligne)? Comment $ query est-il mis à jour?
Mgamerz
@Mgamerz Je vois ce que tu veux dire maintenant. Oui, vous devrez répéter la première ligne à chaque fois pour vérifier si des $urlparamètres sont déjà définis. Édité.
rybo111
1
Ne gère pas les URL avec #.
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
la source
Il suffit d' utiliser: echo http_build_url($url, array("query" => "the=query&parts=here"), HTTP_URL_JOIN_QUERY);. Mais vous aurez besoin pecl install pecl_httpou installez jakeasmith / http_build_url via composer.
Ema4rl
8

Utilisez des strpos pour détecter un?. Depuis ? ne peut apparaître dans l'URL qu'au début d'une chaîne de requête, vous savez si ses paramètres existent déjà et vous devez ajouter des paramètres en utilisant &

function addGetParamToUrl(&$url, $varName, $value)
{
    // is there already an ?
    if (strpos($url, "?"))
    {
        $url .= "&" . $varName . "=" . $value; 
    }
    else
    {
        $url .= "?" . $varName . "=" . $value;
    }
}
Doug T.
la source
Bonne et facile approche si vous êtes préoccupé par les performances, car ce sera beaucoup plus rapide que parse_url et aussi moins intensif en CPU. Le compromis est qu'il ne recherche pas un $ varName existant.
Dennis Stücken
8

Cette fonction écrase un argument existant

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
la source
Que se passe-t-il s'il n'y a pas d' $info['query']ensemble? Vous ne l'avez pas expliqué.
Darren
S'il n'est pas défini, $ info ['query'] devient NULL et $ query devient un tableau vide. Ce n'est donc pas un problème.
Ajay Singh
7

Exemple avec mise à jour des paramètres existants.

Également url_encode utilisé, et possibilité de ne pas spécifier la valeur du paramètre

    <?
    /**
     * 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;
    }
Артур Курицын
la source
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
la source
3
excellent travail, ne remplacez la ligne que $query = $a['query'] ? $a['query'] : '';par$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
la source
3
$parameters = array();

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

$url = 'http://example.com/movies?'.implode('&', $parameters);
TaylorOtwell
la source
3

Je pense que tu devrais faire quelque chose comme ça.

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
la source
1

Après avoir recherché de nombreuses ressources / réponses sur ce sujet, j'ai décidé de coder les miennes. Sur la base de la réponse de @ TaylorOtwell ici, voici comment je traite la requête $ _GET entrante et modifie / manipule chaque élément.

En supposant que l'URL est: http://domaine.com/category/page.php?a=b&x=y Et je ne veux qu'un seul paramètre pour le tri: soit? Desc = nom_colonne ou? Asc = nom_colonne. De cette façon, un seul paramètre d'url suffit pour trier et ordonner simultanément. Ainsi, l'URL sera http://domain.com/category/page.php?a=b&x=y&desc=column_name au premier clic de la ligne d'en-tête de tableau associée.

Ensuite, j'ai des en-têtes de ligne de tableau que je veux trier DESC sur mon premier clic, et ASC sur le deuxième clic du même en-tête. (Chaque premier clic doit d'abord "ORDER BY column DESC") Et s'il n'y a pas de tri, il triera par "date puis id" par défaut.

Vous pouvez l'améliorer davantage, comme vous pouvez ajouter des fonctions de nettoyage / filtrage à chaque composant $ _GET, mais la structure ci-dessous pose les bases.

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, '&');}

(Vous pouvez utiliser $ _SERVER [SCRIPT_URI] pour l'URL complète commençant par http://domain.com )

Ensuite, j'utilise $ ORDER obtenu ci-dessus, dans la requête MySQL:

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

Maintenant, la fonction pour regarder l'URL s'il y a un tri précédent et ajouter le paramètre de tri (et de classement) à l'URL avec "?" ou "&" selon la séquence:

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

Enfin, l'en-tête de ligne du tableau pour utiliser la fonction:

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

Résumé: cela lira l'URL, modifiera chacun des composants $ _GET et créera l'URL finale avec les paramètres de votre choix avec la forme correcte d'utilisation de "?" et "&"

Tarik
la source
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
la source
0

une autre version de fonction améliorée. Mélange de réponses existantes avec de petites améliorations (prise en charge du port) et des corrections de bogues (vérification des clés correctement).

/**
 * @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;
}
Romain86
la source
0

Essayez cette fonction pour ajouter des paramètres d'URL .

Ensuite, vous pouvez désactiver le lien lorsque le paramètre est défini afin qu'il n'y ait pas de doublon de paramètre d'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
la source