使用多个同名值解析查询字符串(复选框,选择多个)而不更改表单

时间:2017-04-28 18:11:22

标签: php html forms

我正在尝试使用<select multiple>或几个具有相同名称的<input type="checkbox">在PHP中读取由HTML表单生成的查询字符串,并且我希望看到与每个名称关联的所有值。这种形式的一个例子:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Form</title>
</head>
<body>
<h1>Form</h1>

<h2>Select</h2>
<form method="get" action="script.php">
<select multiple name="cantchange" size=5>
  <option value="a">Alpha</option>
  <option value="b">Bravo</option>
  <option value="c">Charlie</option>
  <option value="d">Delta</option>
  <option value="e">Echo</option>
</select><br>
Ctrl+click to choose multiple items, then
<input type="submit" name="op" value="Submit">
</form>

<h2>Checkbox set</h2>
<form method="get" action="script.php">
<label><input type="checkbox" name="cantchange" value="f"> Foxtrot</label><br>
<label><input type="checkbox" name="cantchange" value="g"> Golf</label><br>
<label><input type="checkbox" name="cantchange" value="h"> Hotel</label><br>
<label><input type="checkbox" name="cantchange" value="i"> India</label><br>
<label><input type="checkbox" name="cantchange" value="j"> Juliett</label><br>
<input type="submit" name="op" value="Submit">
</form>

</body>
</html>

这将生成以下形式的查询字符串:

cantchange=a&cantchange=b&cantchange=c&op=Submit

但是当PHP将此查询字符串解析为$_GET时,它只会看到每个名称的最后一个值。

How to get multiple selected values of select box in php?”及其重复内容的答案建议将[]附加到表单中每个nameselect元素的input属性中以制作PHP将值收集到数组中。但这假设解释表单的脚本的作者可以更改表单。这并不总是可行的。即使我可以更改表单,添加括号也会显示应用程序是用PHP编写的,诱使入侵者首先尝试针对服务器的特定于PHP的攻击。<​​/ p>

1 个答案:

答案 0 :(得分:0)

如果您无法更改表单,则必须自己完成更多解析查询字符串的工作。首先在&拆分查询字符串,在=拆分每个名称 - 值对,并取消名称和值。以下脚本使用重新实现Python's query string parser API的大部分内容的函数来解析这样的表单。

<?php
// Parse query string from <select multiple> without changing the
// form to add brackets to the element's name attribute.
// Implements a subset of Python's urllib.parse.parse_* APIs
// <https://docs.python.org/3/library/urllib.parse.html>
// Copyright 2017 Damian Yerrick
// License: WTFPL v2 <http://www.wtfpl.net/txt/copying/>

/**
 * Parses an application/x-www-form-urlencoded string, such as the
 * output of http_build_query(), into an array of 2-arrays.
 * @param $qs the query string to parse
 * @param $keep_blank_values if false, omit pairs whose values are ''
 * @return data in the form [[key, value], ...]
 */
function parse_qsl($qs, $keep_blank_values=false) {
  $qs = explode("&", $qs);
  $out = [];
  foreach ($qs as $pair) {
    $pair = explode("=", $pair, 2);
    if (count($pair) != 2) continue;
    $value = urldecode($pair[1]);
    if ($keep_blank_values || $value !== '') {
      $key = urldecode($pair[0]);
      $out[] = [$key, $value];
    }
  }
  return $out;
}

/**
 * Parses an application/x-www-form-urlencoded string into an
 * associative array from keys to arrays of values.
 * @param $qs the query string to parse
 * @param $keep_blank_values if false, omit pairs whose values are ''
 * @param data in the form [key=>[value, ...], ...]
 */
function parse_qs($qs, $keep_blank_values=false) {
  $data = parse_qsl($qs, $keep_blank_values);
  $out = [];
  foreach ($data as $pair) {
    list($key, $value) = $pair;
    if (!array_key_exists($key, $out)) {
      $out[$key] = [];
    }
    $out[$key][] = $value;
  }
  return $out;
}

function hrepr($value) {
  return htmlspecialchars(var_export($value, true));
}

?><!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Form</title>
</head>
<body>
<h1>Form</h1>
<pre>
$_GET is <?=hrepr($_GET)?>

Query string is <?=hrepr($_SERVER['QUERY_STRING'])?>

parse_qsl is <?=hrepr(parse_qsl($_SERVER['QUERY_STRING']))?>

parse_qs is <?=hrepr(parse_qs($_SERVER['QUERY_STRING']))?>
</pre>
</body>
</html>