Как получить несколько параметров с одинаковым именем из URL-адреса в PHP
У меня есть PHP-приложение, которому иногда придется обрабатывать URL-адреса, где несколько параметров в URL-адресе будут иметь одно и то же имя. Есть ли простой способ получить все значения для данного ключа? PHP $_GET возвращает только последнее значение.
Чтобы сделать это конкретным, мое приложение является распознавателем openURL и может получать параметры URL следующим образом:
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
(Да, я знаю, что это некрасиво, добро пожаловать в мой мир). Обратите внимание, что появляется ключ "rft_id" дважды:
rft_id=info:oclcnum/1903126
rft_id=http://www.biodiversitylibrary.org/bibliography/4323
$_GET
вернет только http://www.biodiversitylibrary.org/bibliography/4323
, более раннее значение (info:oclcnum/1903126
) было перезаписано.
Я хотел бы получить доступ к обоим значениям. Возможно ли это в PHP? Если нет, есть какие-нибудь мысли о том, как справиться с этой проблемой?
7 answers
Что-то вроде:
$query = explode('&', $_SERVER['QUERY_STRING']);
$params = array();
foreach( $query as $param )
{
list($name, $value) = explode('=', $param, 2);
$params[urldecode($name)][] = urldecode($value);
}
Дает вам:
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')
)
Не будет работать для вас, так как похоже, что вы не контролируете строку запроса, но другой правильный ответ: вместо синтаксического анализа строки запроса вы можете добавить '[]' в конец имени, тогда PHP создаст массив элементов.
Т.Е.:
someurl.php?name[]=aaa&name[]=bbb
Даст вам $_GET, выглядящий так:
array(0=>'aaa', 1=>'bbb')
Я думаю, вам придется разобрать $_SERVER['QUERY_STRING']
вручную.
Что-то вроде (непроверенное):
$query = $_SERVER['QUERY_STRING'];
$vars = array();
foreach (explode('&', $query) as $pair) {
list($key, $value) = explode('=', $pair);
$vars[] = array(urldecode($key), urldecode($value));
}
Это должно дать вам массив $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')
)
После того, как я увидел ответ Томалака , мне гораздо больше нравится его формат данных для результирующего массива, поскольку он позволяет получить доступ к определенным ключам по их имени.
Для этого нет необходимости использовать глупые explode
обходные пути. Простое регулярное выражение может легче исправить строку ЗАПРОСА с несколькими аналогичными параметрами:
// Replace `&x=1&x=2` into `x[]=1&x[]=2`
$qs = preg_replace("/(?<=^|&)(\w+)(?==)/", "$1[]", $_SERVER["QUERY_STRING"]);
Тогда это так же просто, как использовать parse_str
:
parse_str($qs, $new_GET);
, который имеет преимущество в правильном декодировании %xy
URL-адрес сразу же ускользает.
Если вы просто хотите, чтобы один или несколько конкретных параметров были извлечены в виде массива, используйте (id|name)
вместо (\w+)
в регулярном выражении.
AFAIK нет способа получить повторяющиеся значения с помощью $_GET
, так как второе значение перезапишет первое
Чтобы обойти это, вы можете получить доступ к необработанной строке запроса с помощью $_SERVER['QUERY_STRING']
, а затем проанализировать ее самостоятельно.
Предполагается, что у вас есть строка запроса, подобная этой:
Param1=2549&appname=appName1&appname=appName2&appname=appName3&appname=appName4&appname=appName5&apptype=thetype&idsess=1231324567980147dzeze55sd4&action=myaction
Вы можете сделать это:
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);
}
Это дает:
array (
'param1' => '2549',
'appname' =>
array (
0 => 'appName1',
1 => 'appName2',
2 => 'appName3',
3 => 'appName4',
4 => 'appName5',
),
'apptype' => 'thetype',
'idsess' => '1231324567980147dzeze55sd4',
'action' => 'myaction',
);
Надеюсь, это поможет;)
Делюсь своей версией этой функции
function parse_mstr($query_string,&$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(isset($query[$k])){
if(is_array($query[$k])){
$query[$k][] = $v;
}else{
$query[$k] = array($query[$k],$v);
}
}else{
$query[$k] = $v;
}
}
}