name="field[] 陣列語法HTML 表單中,同名 checkbox 若要在 PHP 接收為陣列,name 屬性必須以 [] 結尾。否則 PHP 僅會收到最後一個被勾選的值(覆蓋機制)。
<form method="post" action="">
<label><input type="checkbox" name="area[]" value="河北"> 河北</label>
<label><input type="checkbox" name="area[]" value="河南"> 河南</label>
<label><input type="checkbox" name="area[]" value="山西"> 山西</label>
<label><input type="checkbox" name="area[]" value="山東"> 山東</label>
<label><input type="checkbox" name="area[]" value="江蘇"> 江蘇</label>
<label><input type="checkbox" name="area[]" value="浙江"> 浙江</label>
<button type="submit">提交</button>
</form>
<?php
$selected = $_POST['area'] ?? $_GET['area'] ?? [];
if (!is_array($selected)) $selected = []; // 防禦性轉型
// 1. 直接輸出
echo '您選擇了:' . implode('、', $selected);
// 2. 迭代處理
foreach ($selected as $val) {
echo "<div>處理:$val</div>";
}
// 3. 安全過濾(白名單)
$allowed = ['河北','河南','山西','山東','江蘇','浙江'];
$clean = array_intersect($selected, $allowed);
// $clean 只保留合法值
?>
<?php
// 來源:資料庫讀出的字串 "河北,河南" 或陣列 ['河北','河南']
$dbValue = '河北,河南'; // 假設從 DB 讀出
$preselected = array_filter(array_map('trim', explode(',', $dbValue)));
// $preselected = ['河北','河南']
$options = ['河北','河南','山西','山東','江蘇','浙江'];
foreach ($options as $opt) {
$checked = in_array($opt, $preselected, true) ? ' checked' : '';
echo "<label><input type=\"checkbox\" name=\"area[]\" value=\"".htmlspecialchars($opt)."\"$checked> ".htmlspecialchars($opt)."</label> ";
}
?>
$options = [
'hebei' => '河北省',
'henan' => '河南省',
'shanxi' => '山西省',
'shandong'=> '山東省',
];
$preselected = ['hebei', 'shandong']; // 儲存的是 key
foreach ($options as $key => $label) {
$checked = in_array($key, $preselected, true) ? ' checked' : '';
echo "<label><input type=\"checkbox\" name=\"area[]\" value=\"$key\"$checked> $label</label> ";
}
// 接收端
$keys = $_POST['area'] ?? [];
// $keys = ['hebei', 'shandong']
// 可直接用於 WHERE IN 查詢或關聯表寫入
| 問題 | 原因 | 解決 |
|---|---|---|
| 只收到最後一個值 | name 未加 [] | 改為 name="field[] |
未勾選任何時 $_POST['field'] 不存在 | 瀏覽器不送出未勾選的 checkbox | 用 $_POST['field'] ?? [] 並 is_array 防禦 |
| 值包含特殊字元導致 XSS | 直接輸出到 HTML | htmlspecialchars() 編碼 value 與 label |
| 資料庫存逗號字串,查詢不便 | 設計為單欄字串 | 改用 JSON、關聯表或 PostgreSQL array 型別 |
| 大量選項渲染緩慢 | 逐個 echo | 用陣列組裝字串一次輸出、或分頁/虛擬滾動 |
class CheckboxGroup
{
/** @var array $options key=>label */
private array $options;
private string $name;
private array $preselected;
private array $allowedValues;
public function __construct(string $name, array $options, array $preselected = [], array $allowedValues = [])
{
$this->name = $name;
$this->options = $options;
$this->preselected = $preselected;
$this->allowedValues = $allowedValues ?: array_keys($options);
}
public function render(array $attrs = []): string
{
$attrStr = '';
foreach ($attrs as $k => $v) $attrStr .= ' ' . $k . '="' . htmlspecialchars($v) . '"';
$html = '';
foreach ($this->options as $value => $label) {
$checked = in_array($value, $this->preselected, true) ? ' checked' : '';
$html .= "<label$attrStr><input type=\"checkbox\" name=\"" . htmlspecialchars($this->name) . "[]\" value=\"" . htmlspecialchars($value) . "\"$checked> " . htmlspecialchars($label) . "</label> ";
}
return $html;
}
public static function getCleanInput(string $name, array $allowed = []): array
{
$input = $_POST[$name] ?? $_GET[$name] ?? [];
if (!is_array($input)) return [];
return $allowed ? array_intersect($input, $allowed) : $input;
}
}
// 使用範例
$group = new CheckboxGroup('area', [
'hebei' => '河北', 'henan' => '河南', 'shanxi' => '山西',
], ['hebei'], ['hebei','henan','shanxi']);
echo $group->render(['class' => 'form-check-input']);
// 處理端
$clean = CheckboxGroup::getCleanInput('area', ['hebei','henan','shanxi']);
// $clean = ['hebei']
json_encode($clean) 存入,查詢用 JSON_CONTAINS 或 @>。user_area (user_id, area_code),標準化、易查詢、支援外鍵。Checkbox 多選核心在於 name="[]"、伺服器端預設空陣列、in_array 判斷預選、白名單過濾輸入。封裝為可複用元件可大幅減少重複代碼並提升安全性。