ThinkPHP 核心未內建資料庫備份功能,本文提供一個基於 PDO 的 SqlAction 控制器,支援完整匯出資料庫結構 (建庫、建表) 與資料 (INSERT 語句),並自動處理字元集、排序規則、特殊字元跳脫,生成可直接執行的 .sql 檔案供下載。
C('DB_*'),無需重複設定DROP DATABASE、CREATE DATABASE (含字元集/排序)、USE、DROP TABLE、CREATE TABLE、INSERT INTOaddslashes 跳脫,防止 SQL 語法錯誤$flag 參數控制是否匯出資料 (0=僅結構, 1=結構+資料)Content-Disposition: attachment 觸發瀏覽器下載SqlAction.class.php<?php
class SqlAction extends Action {
public function outsql() {
header("Content-Type: text/html; charset=utf-8");
// 讀取 ThinkPHP 資料庫配置
$host = C('DB_HOST');
$db_name = C('DB_NAME');
$user = C('DB_USER');
$password = C('DB_PWD');
// 呼叫私有匯出方法
$outstream = $this->outputSql($host, $db_name, $user, $password);
// 觸發下載
header("Content-Disposition: attachment; filename={$db_name}.sql");
echo $outstream;
}
/**
* 資料庫匯出核心方法
* @param string $host 主機位址
* @param string $dbname 資料庫名稱
* @param string $user 使用者名稱
* @param string $password 密碼
* @param int $flag 0=僅結構, 1=結構+資料 (預設)
* @return string 完整 SQL 字串
*/
private function outputSql($host, $dbname, $user, $password, $flag = 1) {
try {
$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";
// 取得建庫語句以擷取字元集
$creat_db = $pdo->query("SHOW CREATE DATABASE `$dbname`")->fetch();
preg_match('/DEFAULT CHARACTER SET (.*)\*/', $creat_db['Create Database'], $matches);
$mysql .= "CREATE DATABASE `$dbname` DEFAULT CHARACTER SET {$matches[1]}";
// 取得排序規則
$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";
// 遍歷所有資料表
$statments = $pdo->query("SHOW TABLES");
foreach ($statments as $value) {
$table_name = $value[0];
$mysql .= "DROP TABLE IF EXISTS `$table_name`;\n";
// 取得建表語句
$table_query = $pdo->query("SHOW CREATE TABLE `$table_name`");
$create_sql = $table_query->fetch();
$mysql .= $create_sql['Create Table'] . ";\r\n\r\n";
// 匯出資料
if ($flag != 0) {
$iteams_query = $pdo->query("SELECT * FROM `$table_name`");
$values = "";
$items = "";
while ($item_query = $iteams_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;
}
}
?>
Lib/Action/SqlAction.class.phphttps://yourdomain.com/index.php/Sql/outsql資料庫名.sqlmysql -u root -p < backup.sql 還原gzencode() 壓縮並分割下載crontab + CLI 模式 (php index.php Sql outsql) 實現自動化備份pdo_mysql 擴展memory_limit 或 max_execution_time,建議 CLI 模式執行並調整參數SHOW CREATE 等專用語法BLOB/TEXT 大欄位的表匯出 INSERT 可能極大,需評估可行性此功能模組化程度高,可直接移植至任何 ThinkPHP 專案,快速擁有資料庫備份下載能力。