Como chegar vários parâmetros com o mesmo nome a partir de uma URL em PHP

votos
40

Tenho uma aplicação PHP que vai de vez em quando tem que lidar com URLs onde mais de um parâmetro na URL terá o mesmo nome. Existe uma maneira fácil de recuperar todos os valores para uma determinada chave? PHP $ _GET retorna apenas o último valor.

Para fazer este concreto, a minha candidatura é um resolvedor OpenURL, e pode obter parâmetros de URL como este:

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

(Sim, eu sei que é feio, bem-vindo ao meu mundo). Note que o rft_id chave aparece duas vezes:

  1. rft_id=info:oclcnum/1903126
  2. rft_id=http://www.biodiversitylibrary.org/bibliography/4323

$_GETretornará apenas http://www.biodiversitylibrary.org/bibliography/4323, o valor anterior ( info:oclcnum/1903126) ter sido substituído.

Eu gostaria de ter acesso a ambos os valores. Isso é possível em PHP? Se não, todos os pensamentos sobre como lidar com este problema?

Publicado 09/12/2008 em 17:33
fonte usuário
Em outras línguas...                            


7 respostas

votos
63

Algo como:

$query  = explode('&', $_SERVER['QUERY_STRING']);
$params = array();

foreach( $query as $param )
{
  list($name, $value) = explode('=', $param, 2);
  $params[urldecode($name)][] = urldecode($value);
}

da-te:

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')
)
Respondeu 09/12/2008 em 17:46
fonte usuário

votos
37

não vai funcionar para você como parece que você não controla a querystring, mas outra resposta válida: Em vez de querystring de análise, você poderia appeand '[]' ao final do nome, então PHP fará uma matriz do Unid.

IE:

someurl.php?name[]=aaa&name[]=bbb

vai lhe dar um $ _GET parecendo:

array(0=>'aaa', 1=>'bbb')
Respondeu 09/12/2008 em 17:41
fonte usuário

votos
9

Eu acho que você teria que analisar $_SERVER['QUERY_STRING']manualmente.

Algo como (não testado):

$query = $_SERVER['QUERY_STRING'];
$vars = array();
foreach (explode('&', $query) as $pair) {
    list($key, $value) = explode('=', $pair);
    $vars[] = array(urldecode($key), urldecode($value));
}

Isso deve lhe dar um array $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')
)

Depois de ter visto do Tomalak resposta, eu gosto de seu formato de dados para a matriz que resulta muito melhor, pois torna-se possível acessar as chaves específicas pelo seu nome.

Respondeu 09/12/2008 em 17:37
fonte usuário

votos
4

Não há necessidade de usar estúpidas explodesoluções para isso. A regex simples pode mais facilmente corrigir um QUERY_STRING com vários parâmetros com o mesmo nome:

// Replace `&x=1&x=2` into `x[]=1&x[]=2`
$qs = preg_replace("/(?<=^|&)(\w+)(?==)/", "$1[]", $_SERVER["QUERY_STRING"]);

Então é tão simples quanto usar parse_str:

parse_str($qs, $new_GET);

Que tem a vantagem de decodificar corretamente %xyURL escapa imediatamente.

Se você quer apenas um único ou alguns parâmetros específicos extraídos como matriz, em seguida, usar (id|name), em vez de (\w+)na regex.

Respondeu 21/09/2015 em 17:34
fonte usuário

votos
2

AFAIK não há nenhuma maneira de obter valores duplicados usando $_GETcomo o segundo valor irá substituir o primeiro

Para contornar o problema você poderá acessar a querystring raw usando $_SERVER['QUERY_STRING']e, em seguida, analisá-lo sozinho.

Respondeu 09/12/2008 em 17:38
fonte usuário

votos
1

Compartilhando minha versão desta função

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;
        }
    }
}
Respondeu 09/05/2013 em 15:21
fonte usuário

votos
1

Assumindo que você tem uma cadeia de consulta como esta:

param1 = 2549 & appname = appName1 & appname = appName2 & appname = appName3 & appname = appName4 & appname = appName5 & APPTYPE = thetype & idsess = 1231324567980147dzeze55sd4 & action = MyAction

Você consegue fazer isso :

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

Isso dá :

array (
  'param1' => '2549',
  'appname' => 
      array (
        0 => 'appName1',
        1 => 'appName2',
        2 => 'appName3',
        3 => 'appName4',
        4 => 'appName5',
  ),
  'apptype' => 'thetype',
  'idsess' => '1231324567980147dzeze55sd4',
  'action' => 'myaction',
);

Espero que ajude ;)

Respondeu 04/07/2012 em 17:18
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more