首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

PHP 獲取 MySQL 所有表資訊現代化實踐:PDO + INFORMATION_SCHEMA 完全替代 mysql_list_tables

     編輯:MySQL 綜合教學

mysql_list_tables() 自 PHP 4.3 起棄用,PHP 7.0 移除。現代 PHP 應用必須使用 PDO (PHP Data Objects) 搭配 INFORMATION_SCHEMA 或 SHOW TABLES,並配合預處理語句、異常處理、型別安全。本文提供三種標準實現、效能對比、遷移清單、常見坑點。

一、為什麼棄用 mysql_list_tables?

  • 擴展移除:ext/mysql PHP 7.0 移除,僅保留 mysqli、PDO_MySQL
  • 無預處理:資料庫名稱直接拼接 SQL,注入風險
  • 無異常機制:回傳 false 需手動檢查,易漏錯
  • 無型別提示:IDE 靜態分析無法覆蓋

二、方案對比

方案SQL 來源優點缺點推薦場景
PDO + INFORMATION_SCHEMA.TABLES標準 SQL跨資料庫標準、可攜帶、支援過濾 (BASE TABLE/VIEW)、可 JOIN 統計資訊權限需 SELECT ON INFORMATION_SCHEMA、MySQL 早期版本較慢通用、需額外元數據 (表大小、引擎、行數)
PDO + SHOW TABLESMySQL 專用簡潔、MySQL 內部優化快、無額外權限非標準、難以擴展過濾條件、無法直接獲取表類型純 MySQL 環境、只需表名列表
mysqli + SHOW TABLESMySQL 專用原生擴展、支援預處理、程序式/物件雙介面綁定 mysqli、非 PDO 通用舊專案 mysqli 遷移、不想引入 PDO

三、標準實現:PDO + INFORMATION_SCHEMA (推薦)


prepare($sql);
    $stmt->bindValue(':db', $database, PDO::PARAM_STR);
    $stmt->bindValue(':type', $tableType, PDO::PARAM_STR);
    $stmt->execute();

    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

// 使用範例
try {
    $dsn = 'mysql:host=127.0.0.1;port=3306;dbname=mydb;charset=utf8mb4';
    $pdo = new PDO($dsn, 'app_user', 'strong_password', [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES => false,  // 真實預處理
        PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4 COLLATE utf8mb4_general_ci"
    ]);

    $tables = getTables($pdo, 'mydb');
    foreach ($tables as $t) {
        echo "{$t['TABLE_NAME']} ({$t['ENGINE']}) ~{$t['TABLE_ROWS']} rows\n";
    }
} catch (PDOException $e) {
    error_log('DB Error: ' . $e->getMessage());
    throw new RuntimeException('Database unavailable', 0, $e);
}

四、輕量實現:PDO + SHOW TABLES


function getTableNames(PDO $pdo, string $database): array {
    $stmt = $pdo->prepare('SHOW TABLES FROM `' . $pdo->quote($database) . '`');
    // 注意:SHOW TABLES 不支援預處理佔位符,需手動 quote 識別符
    $stmt->execute();
    return $stmt->fetchAll(PDO::FETCH_COLUMN, 0);  // 只取第一欄
}

五、進階:獲取表結構 (COLUMNS、INDEXES、FK)


function getTableSchema(PDO $pdo, string $database, string $table): array {
    $cols = $pdo->prepare('
        SELECT COLUMN_NAME, DATA_TYPE, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT,
               COLUMN_KEY, EXTRA, COLUMN_COMMENT
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_SCHEMA = :db AND TABLE_NAME = :tbl
        ORDER BY ORDINAL_POSITION
    ');
    $cols->execute([':db' => $database, ':tbl' => $table]);

    $idxs = $pdo->prepare('
        SELECT INDEX_NAME, COLUMN_NAME, NON_UNIQUE, SEQ_IN_INDEX, INDEX_TYPE
        FROM INFORMATION_SCHEMA.STATISTICS
        WHERE TABLE_SCHEMA = :db AND TABLE_NAME = :tbl
        ORDER BY INDEX_NAME, SEQ_IN_INDEX
    ');
    $idxs->execute([':db' => $database, ':tbl' => $table]);

    return [
        'columns' => $cols->fetchAll(PDO::FETCH_ASSOC),
        'indexes' => $idxs->fetchAll(PDO::FETCH_ASSOC)
    ];
}

六、效能與權限注意事項

項目說明
INFORMATION_SCHEMA 權限需 GRANT SELECT ON INFORMATION_SCHEMA.* TO 'app_user'@'%'; (MySQL 8.0 預設有)
大量表效能超過 1000 表時 INFORMATION_SCHEMA 明顯變慢,建議緩存結果 (Redis TTL 5-10 分鐘)
SHOW TABLES 效能MySQL 內部快取,極快,但無法過濾 VIEW/BASE TABLE
識別符引用資料庫/表名含特殊字元時,用 `quote()` 或 `$pdo->quote()` (僅字串值),識別符需手動反引號包裹

七、遷移清單:從 mysql_list_tables 到 PDO

  1. 確認 PHP 版本 ≥ 7.1 (建議 8.1+),安裝 php-pdo、php-pdo-mysql
  2. 建立統一 Database::getPdo() 單例/工廠,配置 ATTR_ERRMODE=EXCEPTION
  3. 替換所有 mysql_list_tables($db) → getTables($pdo, $db)
  4. 替換 mysql_fetch_row() 迴圈 → foreach ($tables as $row)
  5. 移除 @ 抑制錯誤,統一 try-catch (PDOException)
  6. 執行靜態分析 (Psalm/PHPStan Level 5+) 檢查型別安全
  7. 壓測驗證效能、記憶體、連線池行為

八、Laravel / Symfony / Yii2 框架原生做法

$tables = Schema::connection('mysql')->getTableListing();$tables = $em->getConnection()->getSchemaManager()->listTables();$tables = Yii::$app->db->getSchema()->getTableNames();
框架API範例
LaravelSchema::getTableListing()
Symfony (Doctrine)$conn->getSchemaManager()->listTables()
Yii2yii\db\Schema::getTableNames()

拋棄 mysql_list_tables 不僅是語法遷移,更是邁向型別安全、異常驅動、可測試、框架無關的現代 PHP 工程化關鍵步驟。下一篇我們將探討 Linux 系統下 MySQL 重要目錄結構、密碼管理與 systemd 服務化運維標準化,敬請期待。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved