Строка parse, содержащая точки в php

Я бы проанализировал следующую строку:

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

Я хочу, чтобы $ f анализировался на:

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

Фактически, parse_str возвращается

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

Помимо написания моей собственной функции, знает ли кто-нибудь, есть ли для этого функция php?

Из руководства PHP :

Точки и пробелы в именах переменных преобразуются в символы подчеркивания. Например <input name="ab" /> становится $_REQUEST["a_b"] .

Таким образом, это невозможно. parse_str() преобразует все периоды в parse_str() подчеркивания. Если вы действительно не можете избежать использования периодов в именах переменных запроса, вам нужно будет написать пользовательскую функцию для этого.

Следующая функция (взятая из этого ответа ) преобразует имена каждой пары ключ-значение в строке запроса в соответствующую шестнадцатеричную форму, а затем выполняет parse_str() . Затем они возвращаются в исходную форму. Таким образом, периоды не затрагиваются:

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

Пример использования:

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

Быстро 'n' грязный.

 $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" } 

Эта быстро сделанная функция пытается правильно разобрать строку запроса и возвращает массив.

Второй (необязательный) параметр $break_dots сообщает синтаксическому анализатору создать $break_dots при столкновении с точкой (это выходит за рамки вопроса, но я все равно включил его).

 /** * 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; } с /** * 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; } с /** * 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; } с /** * 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; } 

Я попытался правильно обрабатывать многоуровневые ключи. Код немного взломан, но он должен работать. Я попытался прокомментировать код, прокомментируйте, если у вас есть какие-либо вопросы.

Прецедент:

 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" // } // }