首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

MySQL ENUM 欄位值動態獲取:PHP 實作範例

     編輯:PHP 相關知識

需求背景

資料庫設計時使用 ENUM 類型限定欄位值(如狀態碼、分類),前端表單需要動態產生下拉選單選項,避免硬編碼導致資料庫與程式碼不同步。

核心 SQL 語法

SHOW COLUMNS FROM `table_name` LIKE 'enum_column_name'

回傳結果中 Type 欄位格式為:enum('value1','value2','value3')

PHP 完整實作範例

<?php
/**
 * 獲取 MySQL ENUM 欄位所有可能值
 * @param PDO $pdo 資料庫連線
 * @param string $table 資料表名稱
 * @param string $column 欄位名稱
 * @return array 列舉值陣列
 * @throws Exception
 */
function getEnumValues(PDO $pdo, string $table, string $column): array {
    // 防止 SQL 注入:驗證表名、欄位名格式
    if (!preg_match('/^[a-zA-Z0-9_]+$/', $table) || !preg_match('/^[a-zA-Z0-9_]+$/', $column)) {
        throw new InvalidArgumentException('無效的表名或欄位名');
    }

    $sql = "SHOW COLUMNS FROM `$table` LIKE ?";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([$column]);
    $row = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$row) {
        throw new Exception("找不到欄位:$table.$column");
    }

    $type = $row['Type']; // 例:enum('Y','N','P')
    
    // 解析 enum 定義
    if (!preg_match("/^enum\((.+)\)$/i", $type, $matches)) {
        throw new Exception("欄位 $column 非 ENUM 類型");
    }

    $enumList = $matches[1]; // 'Y','N','P'
    
    // 移除引號並分割
    $values = array_map(function($v) {
        return trim($v, "'\" "); // 移除單雙引號與空白
    }, explode(',', $enumList));

    return $values;
}

// ===== 使用範例 =====
try {
    // 資料庫連線設定
    $dsn = 'mysql:host=localhost;dbname=test_db;charset=utf8mb4';
    $pdo = new PDO($dsn, 'username', 'password', [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    ]);

    // 獲取使用者表狀態欄位的 enum 值
    $statusValues = getEnumValues($pdo, 'users', 'status');
    
    // 輸出 HTML 選單
    echo '<select name="status">';
    foreach ($statusValues as $value) {
        $label = match($value) {
            'A' => '啟用',
            'I' => '停用',
            'P' => '審核中',
            default => $value,
        };
        echo "<option value=\"$value\">$label</option>";
    }
    echo '</select>';
    
    // 或輸出 JSON 供前端 AJAX 使用
    header('Content-Type: application/json');
    echo json_encode($statusValues);

} catch (Exception $e) {
    error_log($e->getMessage());
    http_response_code(500);
    echo json_encode(['error' => '無法獲取列舉值']);
}
?>

進階應用:快取機制

ENUM 定義極少變更,建議快取減少資料庫查詢:

<?php
function getEnumValuesCached(PDO $pdo, string $table, string $column): array {
    $cacheKey = "enum_values_{$table}_{$column}";
    
    // 假設使用 Redis 快取
    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);
    
    if ($redis->exists($cacheKey)) {
        return json_decode($redis->get($cacheKey), true);
    }
    
    $values = getEnumValues($pdo, $table, $column);
    $redis->set($cacheKey, json_encode($values), 86400); // 快取 24 小時
    return $values;
}
?>

替代方案比較

方案優點缺點適用場景
ENUM + 動態查詢資料庫層級約束、儲存空間小修改需 ALTER TABLE、跨資料庫移植性差固定不變的分類(性別、狀態)
查找表 + 外鍵彈性擴充、標準化、易維護需 JOIN 查詢、略佔空間可能擴充的分類(商品類別、地區)
前端硬編碼簡單、無額外查詢易不同步、維護困難極少變更、極簡單專案

注意事項

  1. 權限:資料庫使用者需有 SHOW COLUMNS 權限
  2. 編碼:確保連線字元集與資料表一致(建議 utf8mb4)
  3. 大小寫:MySQL ENUM 值區分大小寫,查詢時注意
  4. NULL 值:ENUM 可允許 NULL,解析時不包含 NULL
  5. 預設值:可從 Default 欄位取得預設值

擴展:獲取完整欄位定義

<?php
function getColumnDefinition(PDO $pdo, string $table, string $column): array {
    $sql = "SHOW COLUMNS FROM `$table` LIKE ?";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([$column]);
    return $stmt->fetch(PDO::FETCH_ASSOC) ?: [];
}

// 回傳陣列結構:
// [
//   'Field' => 'status',
//   'Type' => "enum('A','I','P')",
//   'Null' => 'NO',
//   'Key' => '',
//   'Default' => 'P',
//   'Extra' => ''
// ]
?>
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved