ThinkPHP 早期版本缺乏內建數據庫備份功能。本文提供一個基於 PDO 的完整備份類,支持數據庫結構(DDL)與數據(DML)的一鍵導出,生成標準 SQL 文件供下載,可直接用於遷移或恢復。
<?php
class SqlAction extends Action {
public function outsql() {
header("Content-Type: text/html; charset=utf-8");
// 從配置讀取數據庫信息
$host = C('DB_HOST');
$db_name = C('DB_NAME');
$user = C('DB_USER');
$password = C('DB_PWD');
// 調用私有方法生成 SQL 內容
$outstream = $this->outputSql($host, $db_name, $user, $password);
// 觸發文件下載
header("Content-Disposition: attachment; filename={$db_name}.sql");
echo $outstream;
}
// ... 私有方法見下文
}
?>
private function outputSql($host, $dbname, $user, $password, $flag = 1) {
try {
// 1. 建立 PDO 連接,啟用異常模式
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $user, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo $e->getMessage();
exit;
}
$mysql = "DROP DATABASE IF EXISTS `$dbname`;\n";
// 2. 獲取數據庫創建語句,提取字符集
$creat_db = $pdo->query("SHOW CREATE DATABASE `$dbname`")->fetch();
preg_match('/DEFAULT CHARACTER SET\s+(\w+)/', $creat_db['Create Database'], $matches);
$mysql .= "CREATE DATABASE `$dbname` DEFAULT CHARACTER SET {$matches[1]}";
// 3. 獲取排序規則
$db_collate = $pdo->query("SELECT DEFAULT_COLLATION_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = '$dbname' LIMIT 1")->fetch();
$mysql .= " COLLATE {$db_collate['DEFAULT_COLLATION_NAME']};\nUSE `$dbname`;\n\n";
// 4. 遍歷所有表
$statments = $pdo->query("SHOW TABLES");
foreach ($statments as $value) {
$table_name = $value[0];
$mysql .= "DROP TABLE IF EXISTS `$table_name`;\n";
// 4.1 導出表結構
$table_query = $pdo->query("SHOW CREATE TABLE `$table_name`");
$create_sql = $table_query->fetch();
$mysql .= $create_sql['Create Table'] . ";\r\n\r\n";
// 4.2 導出表數據 (若 $flag != 0)
if ($flag != 0) {
$items_query = $pdo->query("SELECT * FROM `$table_name`");
$values = "";
$items = "";
while ($item_query = $items_query->fetch(PDO::FETCH_ASSOC)) {
// 字段名處理
$item_names = array_keys($item_query);
$item_names = array_map('addslashes', $item_names);
$items = join('`,`', $item_names); // 反引號包裹
// 字段值處理
$item_values = array_values($item_query);
$item_values = array_map('addslashes', $item_values);
$value_string = join("','", $item_values); // 單引號包裹
$value_string = "('" . $value_string . "'),";
$values .= "\n" . $value_string;
}
if ($values) {
$insert_sql = "INSERT INTO `$table_name` (`$items`) VALUES" . rtrim($values, ",") . ";\n\r";
$mysql .= $insert_sql;
}
}
}
return $mysql;
}
這個備份類雖然簡潔,但涵蓋了數據庫導出的核心邏輯,是理解 MySQL 元數據操作與 SQL 生成的優秀教學案例,也可直接移植到項目中作為應急備份工具使用。