web-dev-qa-db-fra.com

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

Je souhaite ajouter des paramètres GET à des URL susceptibles de contenir ou non 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 est juste une chaîne.

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

64
Ryan

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);
parse_str($url_parts['query'], $params);

$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 mettre cela au moins dans une fonction, sinon dans une classe.

143
andrewtweber

Voici une version abrégée de la réponse acceptée:

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

Edit: comme indiqué dans la réponse acceptée, ceci est erroné car il ne vérifie pas si category existe déjà. Une meilleure solution serait de traiter le $_GET pour ce qu’il est - un tableau - et d’utiliser des fonctions telles que in_array().

40
rybo111
$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
15
Tom Claus

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

Utilisez strpos pour détecter un?. Puisque ? ne peut apparaître que dans l'URL 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 à l'aide de &

function addGetParamToUrl(&$url, $varName, $value)
{
    // is there already an ?
    if (strpos($url, "?"))
    {
        $url .= "&" . $varName . "=" . $value; 
    }
    else
    {
        $url .= "?" . $varName . "=" . $value;
    }
}
8
Doug T.

Exemple avec la mise à jour des paramètres existants.

En outre, 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;
    }
<?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";
4
shengbin_xu

Je pense que vous devriez 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;
3
Hammerite
$parameters = array();

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

$url = 'http://example.com/movies?'.implode('&', $parameters);
2
TaylorOtwell
 /**
 * @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;
}
2
Londeren

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

En supposant que l'URL est: http://domain.com/category/page.php?a=b&x=y Et je ne souhaite qu'un seul paramètre pour le tri:? 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 table associée.

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

Vous pouvez l’améliorer davantage, tout 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 une URL complète commençant par http://domain.com )

Ensuite, j'utilise le résultat $ ORDER I obtenu ci-dessus, dans la requête MySQL:

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

Maintenant, la fonction permet de regarder l'URL s'il existe un tri précédent et d'ajouter un 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 la ligne de la table pour utiliser la fonction:

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

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

1
Tarik

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 d'éviter toute duplication du 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>
0
csandreas1

Je pense que c'est ce que vous cherchez:

paramètres url regex

0
fingerman
 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;
}
0
Maor

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 de corrections de bugs (vérification correcte des clés).

/**
 * @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;
}
0
Roman86