<?php
/**
* 通用資料庫查詢生成下拉選單
* @param PDO $pdo 資料庫連線
* @param string $table 表名
* @param string $valueCol 值欄位(option value)
* @param string $displayCol 顯示欄位(option 文字)
* @param array $where 條件陣列 ['col' => 'val', ...]
* @param string $orderBy 排序欄位
* @param string $selected 預設選中值
* @param string $placeholder 首選項提示文字
* @param array $attributes 額外 select 屬性 ['id'=>'mySelect', 'class'=>'form-control']
* @return string HTML select 標籤
*/
function buildSelectFromTable(
PDO $pdo,
string $table,
string $valueCol,
string $displayCol,
array $where = [],
string $orderBy = '',
string $selected = '',
string $placeholder = '請選擇',
array $attributes = []
): string {
// 建構 WHERE 子句
$whereSql = '';
$params = [];
if ($where) {
$conditions = [];
foreach ($where as $col => $val) {
$conditions[] = "`$col` = ?";
$params[] = $val;
}
$whereSql = 'WHERE ' . implode(' AND ', $conditions);
}
// 建構 ORDER BY
$orderSql = $orderBy ? "ORDER BY `$orderBy`" : '';
$sql = "SELECT `$valueCol`, `$displayCol` FROM `$table` $whereSql $orderSql";
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 建構屬性字串
$attrStr = '';
foreach ($attributes as $key => $val) {
$attrStr .= " $key=\"" . htmlspecialchars($val) . "\"";
}
// 產生 HTML
$html = "";
return $html;
}
// 使用範例
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', 'user', 'pass');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 簡單用法
echo buildSelectFromTable($pdo, 'categories', 'id', 'name');
// 進階用法
echo buildSelectFromTable(
$pdo,
'users',
'id',
'username',
['status' => 1, 'role' => 'admin'], // WHERE 條件
'username', // ORDER BY
5, // 預設選中 ID=5
'選擇管理員', // 提示文字
['id' => 'adminSelect', 'class' => 'form-select'] // 屬性
);
?>
| 問題 | 原始碼 | 風險 |
|---|---|---|
| SQL 注入 | 直接拼接 $table, $where | 高 |
| 棄用函數 | mysql_* 系列 | PHP 7.0+ 移除 |
| XSS 風險 | 直接輸出 $data[$field] | 中 |
| 編碼問題 | 無 charset 設定 | 中文亂碼 |
| 錯誤處理 | 無 try-catch | 白畫面 |
// 修改 displayCol 參數為陣列或回呼
function buildSelectAdvanced(PDO $pdo, string $table, string $valueCol, $displaySpec, ...): string {
// ...
if (is_callable($displaySpec)) {
$disp = htmlspecialchars($displaySpec($row));
} elseif (is_array($displaySpec)) {
$parts = array_map(fn($col) => $row[$col] ?? '', $displaySpec);
$disp = htmlspecialchars(implode(' ', $parts));
} else {
$disp = htmlspecialchars($row[$displaySpec]);
}
// ...
}
// 使用
echo buildSelectAdvanced($pdo, 'users', 'id',
fn($row) => "{$row['name']} ({$row['username']})",
['status' => 1]
);
?>
通用下拉選單函數能減少重複程式碼,但需注意 SQL 注入、XSS、編碼、錯誤處理。現代專案建議使用 PDO + 預處理語句,並將 HTML 產生邏輯分離至 View 層(如 Blade、Twig 模板),而非在函數中直接輸出 HTML。