Cadena Parse que contiene puntos en php

Yo analizaría la siguiente cadena:

$str = 'ProceduresCustomer.tipi_id=10&ProceduresCustomer.id=1'; parse_str($str,$f); 

Deseo que $ f sean analizados en:

 array( 'ProceduresCustomer.tipi_id' => '10', 'ProceduresCustomer.id' => '1' ) 

En realidad, el parse_str devuelve

 array( 'ProceduresCustomer_tipi_id' => '10', 'ProceduresCustomer_id' => '1' ) 

Además de escribir mi propia función, ¿alguien sabe si hay una función php para eso?

Del manual de PHP :

Los puntos y espacios en los nombres de las variables se convierten en guiones bajos. Por ejemplo, convierte en $_REQUEST["a_b"] .

Entonces, no es posible. parse_str() convertirá todos los períodos en guiones bajos. Si realmente no puede evitar usar períodos en sus nombres de variable de consulta, tendrá que escribir una función personalizada para lograr esto.

La siguiente función (tomada de esta respuesta ) convierte los nombres de cada par de clave-valor en la cadena de consulta en su forma hexadecimal correspondiente y luego hace un parse_str() en él. Luego, vuelven a su forma original. De esta manera, los períodos no se tocan:

 function parse_qs($data) { $data = preg_replace_callback('/(?:^|(?<=&))[^=[]+/', function($match) { return bin2hex(urldecode($match[0])); }, $data); parse_str($data, $values); return array_combine(array_map('hex2bin', array_keys($values)), $values); } 

Ejemplo de uso:

 $data = parse_qs($_SERVER['QUERY_STRING']); 

Rápido y sucio.

 $str = "ProceduresCustomer.tipi_id=10&ProceduresCustomer.id=1"; function my_func($str){ $expl = explode("&", $str); foreach($expl as $r){ $tmp = explode("=", $r); $out[$tmp[0]] = $tmp[1]; } return $out; } var_dump(my_func($str)); array(2) { ["ProceduresCustomer.tipi_id"]=> string(2) "10" ["ProceduresCustomer.id"]=>string(1) "1" } 

Esta función rápida intenta analizar correctamente la cadena de consulta y devuelve una matriz.

El segundo parámetro (opcional) $break_dots le dice al analizador que cree una sub-matriz al encontrar un punto (esto va más allá de la pregunta, pero lo incluí de todos modos).

 /** * parse_name -- Parses a string and returns an array of the key path * if the string is malformed, only return the original string as a key * * $str The string to parse * $break_dot Whether or not to break on dots (default: false) * * Examples : * + parse_name("var[hello][world]") = array("var", "hello", "world") * + parse_name("var[hello[world]]") = array("var[hello[world]]") // Malformed * + parse_name("var.hello.world", true) = array("var", "hello", "world") * + parse_name("var.hello.world") = array("var.hello.world") * + parse_name("var[hello][world") = array("var[hello][world") // Malformed */ function parse_name ($str, $break_dot = false) { // Output array $out = array(); // Name buffer $buf = ''; // Array counter $acount = 0; // Whether or not was a closing bracket, in order to avoid empty indexes $lastbroke = false; // Loop on chars foreach (str_split($str) as $c) { switch ($c) { // Encountering '[' flushes the buffer to $out and increments the // array counter case '[': if ($acount == 0) { if (!$lastbroke) $out[] = $buf; $buf = ""; $acount++; $lastbroke = false; // In this case, the name is malformed. Return it as-is } else return array($str); break; // Encountering ']' flushes rge buffer to $out and decrements the // array counter case ']': if ($acount == 1) { if (!$lastbroke) $out[] = $buf; $buf = ''; $acount--; $lastbroke = true; // In this case, the name is malformed. Return it as-is } else return array($str); break; // If $break_dot is set to true, flush the buffer to $out. // Otherwise, treat it as a normal char. case '.': if ($break_dot) { if (!$lastbroke) $out[] = $buf; $buf = ''; $lastbroke = false; break; } // Add every other char to the buffer default: $buf .= $c; $lastbroke = false; } } // If the counter isn't back to 0 then the string is malformed. Return it as-is if ($acount > 0) return array($str); // Otherwise, flush the buffer to $out and return it. if (!$lastbroke) $out[] = $buf; return $out; } /** * decode_qstr -- Take a query string and decode it to an array * * $str The query string * $break_dot Whether or not to break field names on dots (default: false) */ function decode_qstr ($str, $break_dots = false) { $out = array(); // '&' is the field separator $a = explode('&', $str); // For each field=value pair: foreach ($a as $param) { // Break on the first equal sign. $param = explode('=', $param, 2); // Parse the field name $key = parse_name($param[0], $break_dots); // This piece of code creates the array structure according to th // decomposition given by parse_name() $array = &$out; // Reference to the last object. Starts to $out $append = false; // If an empty key is given, treat it like $array[] = 'value' foreach ($key as $k) { // If the current ref isn't an array, make it one if (!is_array($array)) $array = array(); // If the current key is empty, break the loop and append to current ref if (empty($k)) { $append = true; break; } // If the key isn't set, set it :) if (!isset($array[$k])) $array[$k] = NULL; // In order to walk down the array, we need to first save the ref in // $array to $tmp $tmp = &$array; // Deletes the ref from $array unset($array); // Create a new ref to the next item $array =& $tmp[$k]; // Delete the save unset($tmp); } // If instructed to append, do that if ($append) $array[] = $param[1]; // Otherwise, just set the value else $array = $param[1]; // Destroy the ref for good unset($array); } // Return the result return $out; } 

Traté de manejar correctamente las claves de varios niveles. El código es un poco raro, pero debería funcionar. Intenté comentar el código, comentar si tienes alguna pregunta.

Caso de prueba:

 var_dump(decode_qstr("ProceduresCustomer.tipi_id=10&ProceduresCustomer.id=1")); // array(2) { // ["ProceduresCustomer.tipi_id"]=> // string(2) "10" // ["ProceduresCustomer.id"]=> // string(1) "1" // } var_dump(decode_qstr("ProceduresCustomer.tipi_id=10&ProceduresCustomer.id=1", true)); // array(1) { // ["ProceduresCustomer"]=> // array(2) { // ["tipi_id"]=> // string(2) "10" // ["id"]=> // string(1) "1" // } // }