J'ai une application PHP qui devra parfois gérer des URL où plus d'un paramètre dans l'URL aura le même nom. Existe-t-il un moyen simple de récupérer toutes les valeurs d'une clé donnée ? PHP $ _GET renvoie uniquement la dernière valeur.
Pour rendre cela concret, mon application est un résolveur OpenURL, et peut obtenir des paramètres URL comme celui-ci:
ctx_ver=Z39.88-2004
&rft_id=info:oclcnum/1903126
&rft_id=http://www.biodiversitylibrary.org/bibliography/4323
&rft_val_fmt=info:ofi/fmt:kev:mtx:book
&rft.genre=book
&rft.btitle=At last: a Christmas in the West Indies.
&rft.place=London,
&rft.pub=Macmillan and co.,
&rft.aufirst=Charles
&rft.aulast=Kingsley
&rft.au=Kingsley, Charles,
&rft.pages=1-352
&rft.tpages=352
&rft.date=1871
(Oui, je sais que c'est moche, bienvenue dans mon monde). Notez que la clé "rft_id" apparaît deux fois:
rft_id=info:oclcnum/1903126
rft_id=http://www.biodiversitylibrary.org/bibliography/4323
$_GET
renverra juste http://www.biodiversitylibrary.org/bibliography/4323
, la valeur précédente (info:oclcnum/1903126
) ayant été écrasé.
J'aimerais avoir accès aux deux valeurs. Est-ce possible en PHP? Sinon, des réflexions sur la façon de gérer ce problème?
Quelque chose comme:
$query = explode('&', $_SERVER['QUERY_STRING']);
$params = array();
foreach( $query as $param )
{
// prevent notice on explode() if $param has no '='
if (strpos($param, '=') === false) $param += '=';
list($name, $value) = explode('=', $param, 2);
$params[urldecode($name)][] = urldecode($value);
}
vous donne:
array(
'ctx_ver' => array('Z39.88-2004'),
'rft_id' => array('info:oclcnum/1903126', 'http://www.biodiversitylibrary.org/bibliography/4323'),
'rft_val_fmt' => array('info:ofi/fmt:kev:mtx:book'),
'rft.genre' => array('book'),
'rft.btitle' => array('At last: a Christmas in the West Indies.'),
'rft.place' => array('London'),
'rft.pub' => array('Macmillan and co.'),
'rft.aufirst' => array('Charles'),
'rft.aulast' => array('Kingsley'),
'rft.au' => array('Kingsley, Charles'),
'rft.pages' => array('1-352'),
'rft.tpages' => array('352'),
'rft.date' => array('1871')
)
Puisqu'il est toujours possible qu'un paramètre d'URL soit répété, il est préférable de toujours avoir des tableaux, au lieu de seulement pour les paramètres où vous les anticipez.
Ne fonctionnera pas pour vous car il semble que vous ne contrôliez pas la chaîne de requête, mais une autre réponse valide: au lieu d'analyser la chaîne de requête, vous pouvez afficher et '[]' à la fin du nom, puis PHP fera un tableau des éléments.
C'EST À DIRE:
someurl.php?name[]=aaa&name[]=bbb
vous donnera un $ _GET ressemblant à:
array(0=>'aaa', 1=>'bbb')
Je pense qu'il faudrait analyser $_SERVER['QUERY_STRING']
manuellement.
Quelque chose comme (non testé):
$query = $_SERVER['QUERY_STRING'];
$vars = array();
foreach (explode('&', $query) as $pair) {
list($key, $value) = explode('=', $pair);
$vars[] = array(urldecode($key), urldecode($value));
}
Cela devrait vous donner un tableau $vars
:
array(
array('ctx_ver' => 'Z39.88-2004'),
array('rft_id' => 'info:oclcnum/1903126'),
array('rft_id' => 'http://www.biodiversitylibrary.org/bibliography/4323'),
array('rft_val_fmt' => 'info:ofi/fmt:kev:mtx:book'),
array('rft.genre' => 'book'),
array('rft.btitle' => 'At last: a Christmas in the West Indies.'),
array('rft.place' => 'London'),
array('rft.pub' => 'Macmillan and co.'),
array('rft.aufirst' => 'Charles'),
array('rft.aulast' => 'Kingsley'),
array('rft.au' => 'Kingsley, Charles'),
array('rft.pages' => '1-352'),
array('rft.tpages' => '352'),
array('rft.date' => '1871')
)
Après avoir vu Tomalak's réponse, j'aime beaucoup mieux son format de données pour le tableau résultant, car il permet d'accéder à des clés spécifiques par leur nom.
Il n'est pas nécessaire d'utiliser des solutions de contournement explode
stupides pour cela. Une simple expression régulière peut plus facilement rectifier un QUERY_STRING avec plusieurs paramètres de même nom:
// Replace `&x=1&x=2` into `x[]=1&x[]=2`
$qs = preg_replace("/(?<=^|&)(\w+)(?==)/", "$1[]", $_SERVER["QUERY_STRING"]);
C'est aussi simple que d'utiliser parse_str
:
parse_str($qs, $new_GET);
Ce qui a l'avantage de décoder correctement %xy
L'URL s'échappe immédiatement.
Si vous souhaitez simplement extraire un ou plusieurs paramètres spécifiques sous forme de tableau, utilisez (id|name)
au lieu de (\w+)
dans l'expression régulière.
AFAIK il n'y a aucun moyen d'obtenir des valeurs en double en utilisant $_GET
car la deuxième valeur écrasera la première
Pour le contourner, vous pouvez accéder à la chaîne de requête brute à l'aide de $_SERVER['QUERY_STRING']
puis analysez-le vous-même.
Supposons que vous ayez une chaîne de requête comme celle-ci:
param1 = 2549 & appname = appName1 & appname = appName2 & appname = appName3 & appname = appName4 & appname = appName5 & apptype = thetype & idsess = 1231324567980147dzeze55sd4 & action = myaction
Tu peux le faire :
public static function getMultipleParameters()
{
$query = $_SERVER['QUERY_STRING'];
$vars = array();
$second = array();
foreach (explode('&', $query) as $pair) {
list($key, $value) = explode('=', $pair);
if('' == trim($value)){
continue;
}
if (array_key_exists($key, $vars)) {
if (!array_key_exists($key, $second))
$second[$key][] .= $vars[$key];
$second[$key][] = $value;
} else {
$vars[$key] = urldecode($value);
}
}
return array_merge($vars, $second);
}
Ça donne :
array (
'param1' => '2549',
'appname' =>
array (
0 => 'appName1',
1 => 'appName2',
2 => 'appName3',
3 => 'appName4',
4 => 'appName5',
),
'apptype' => 'thetype',
'idsess' => '1231324567980147dzeze55sd4',
'action' => 'myaction',
);
J'espère que cela pourra aider ;)
Partager ma version de cette fonction
function parse_mstr($query_string,&$query=array()){
$query = $query? $query: array();
$params = explode('&', $query_string);
foreach( $params as $param ){
$k = $param;
$v = '';
if(strpos($param,'=')){
list($name, $value) = explode('=', $param);
$k = rawurldecode($name);
$v = rawurldecode($value);
}
if(array_key_exists($k, $query)){
if(is_array($query[$k])){
$query[$k][] = $v;
}else{
$query[$k] = array($query[$k],$v);
}
}else{
$query[$k] = $v;
}
}
}
// usage
parse_mstr('a=1&a=2&b=3', $arr);
// resulting array
$arr = [
'a' => ['1', '2'],
'b' => '3'
]