Cómo obtener múltiples parámetros con el mismo nombre de una URL en PHP

votos
40

Tengo una aplicación PHP que en ocasiones tendrá que manejar URL donde más de un parámetro en la URL tendrá el mismo nombre. ¿Hay una manera fácil de recuperar todos los valores para una clave determinada? PHP $ _GET devuelve solo el último valor.

Para hacer esto concreto, mi aplicación es una resolución OpenURL, y puede obtener 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

(Sí, sé que es feo, bienvenido a mi mundo). Tenga en cuenta que la clave rft_id aparece dos veces:

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

$_GETdevolverá solo http://www.biodiversitylibrary.org/bibliography/4323, el valor anterior ( info:oclcnum/1903126) se habrá sobrescrito.

Me gustaría obtener acceso a ambos valores. ¿Es esto posible en PHP? Si no, ¿alguna idea sobre cómo manejar este problema?

Publicado el 09/12/2008 a las 17:33
fuente por usuario
En otros idiomas...                            


7 respuestas

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

te dio:

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')
)
Respondida el 09/12/2008 a las 17:46
fuente por usuario

votos
37

No funcionará para usted, ya que parece que no controla la cadena de consulta, pero es otra respuesta válida: en lugar de analizar la cadena de consulta, podría aparecer '[]' hasta el final del nombre, luego PHP creará una matriz del artículos.

ES DECIR:

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

le dará un $ _GET con aspecto de:

array(0=>'aaa', 1=>'bbb')
Respondida el 09/12/2008 a las 17:41
fuente por usuario

votos
9

Creo que tendrías que analizar $_SERVER['QUERY_STRING']manualmente.

Algo así como (no probado):

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

Esto debería darte una matriz $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')
)

Después de haber visto la respuesta de Tomalak , me gusta mucho más su formato de datos para la matriz resultante, ya que permite acceder a claves específicas por su nombre.

Respondida el 09/12/2008 a las 17:37
fuente por usuario

votos
4

No hay necesidad de usar estúpidos explodesoluciones para esto. Una expresión regular simple puede corregir más fácilmente una QUERY_STRING con múltiples parámetros con nombres similares:

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

Entonces es tan simple como usar parse_str:

parse_str($qs, $new_GET);

Que tiene la ventaja de decodificar correctamente %xyURL escapa de inmediato.

Si lo que desea es una sola o unas pocas parámetros específicos extraídos como matriz, a continuación, utilizar (id|name)en lugar de (\w+)en la expresión regular.

Respondida el 21/09/2015 a las 14:34
fuente por usuario

votos
2

AFAIK no hay forma de obtener valores duplicados, $_GETya que el segundo valor sobrescribirá el primero

Para evitarlo, puede acceder a la cadena de consulta sin procesar $_SERVER['QUERY_STRING']y luego analizarlo usted mismo.

Respondida el 09/12/2008 a las 17:38
fuente por usuario

votos
1

Compartir mi versión de esta función

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;
        }
    }
}
Respondida el 09/05/2013 a las 15:21
fuente por usuario

votos
1

Asumido que tiene una cadena de consulta como esta:

param1 = 2,549 y nombreapl = appName1 y nombreapl = appName2 y nombreapl = appName3 y nombreapl = appName4 y nombreapl = appName5 y tipo de aplicación = eltipo y idsess = 1231324567980147dzeze55sd4 & Action = MyAction

Puedes hacerlo :

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

Eso da :

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

Espero que ayude ;)

Respondida el 04/07/2012 a las 17:18
fuente por usuario

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