{"id":23696,"date":"2024-11-21T13:27:21","date_gmt":"2024-11-21T05:27:21","guid":{"rendered":"https:\/\/fwq.ai\/blog\/23696\/"},"modified":"2024-11-21T13:27:21","modified_gmt":"2024-11-21T05:27:21","slug":"%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8thinkphp6%e5%ae%9e%e7%8e%b0%e6%95%b0%e6%8d%ae%e5%ba%93%e5%a4%87%e4%bb%bd%e4%b8%8e%e6%81%a2%e5%a4%8d","status":"publish","type":"post","link":"https:\/\/fwq.ai\/blog\/23696\/","title":{"rendered":"\u5982\u4f55\u4f7f\u7528ThinkPHP6\u5b9e\u73b0\u6570\u636e\u5e93\u5907\u4efd\u4e0e\u6062\u590d"},"content":{"rendered":"<p>\u5728\u5f00\u53d1\u4e1a\u52a1\u7cfb\u7edf\u8fc7\u7a0b\u4e2d\uff0c\u6570\u636e\u5e93\u662f\u975e\u5e38\u91cd\u8981\u7684\u4e00\u73af\u3002\u56e0\u6b64\uff0c\u5bf9\u6570\u636e\u5e93\u8fdb\u884c\u5907\u4efd\u548c\u6062\u590d\u662f\u975e\u5e38\u5fc5\u8981\u7684\u64cd\u4f5c\u3002\u672c\u6587\u5c06\u7ed3\u54086\u6846\u67b6\u5b9e\u4f8b\uff0c\u4ecb\u7ecd\u5982\u4f55\u4f7f\u7528thinkphp6\u5b9e\u73b0\u6570\u636e\u5e93\u5907\u4efd\u4e0e\u6062\u590d\u3002<\/p>\n<p>\u4e00\u3001\u6570\u636e\u5e93\u5907\u4efd<\/p>\n<p>1.1 \u73af\u5883\u51c6\u5907<\/p>\n<p>\u5728\u8fdb\u884c\u6570\u636e\u5e93\u5907\u4efd\u4e4b\u524d\uff0c\u9700\u8981\u786e\u8ba4\u5982\u4e0b\u51e0\u70b9\uff1a<\/p>\n<p>1\u3001\u9700\u8981\u8bbe\u7f6e\u597dmysql\u6570\u636e\u5e93\u7684bin\u76ee\u5f55\u5730\u5740\uff0c\u5e76\u628a\u5176\u8def\u5f84\u52a0\u5165\u7cfb\u7edfPath\u53d8\u91cf\u4e2d\uff1b<\/p>\n<p><span>\u7acb\u5373\u5b66\u4e60<\/span>\u201c\u201d\uff1b<\/p>\n<p><span>\u70b9\u51fb\u4e0b\u8f7d<\/span>\u201c\u201d\uff1b<\/p>\n<p>2\u3001\u9700\u8981\u5b89\u88c5\u597dmysqldump\u547d\u4ee4\u884c\u5de5\u5177\uff1b<\/p>\n<p>3\u3001\u786e\u8ba4\u5728\u6570\u636e\u5e93\u6240\u5728\u7684\u673a\u5668\u4e0a\uff0c\u6267\u884c\u5907\u4efd\u7684\u7528\u6237\uff0c\u6709\u5bf9\u6570\u636e\u5e93\u6267\u884cmysqldump\u547d\u4ee4\u7684\u6743\u9650\u3002<\/p>\n<p>1.2 \u6570\u636e\u5e93\u5907\u4efd\u5b9e\u73b0<\/p>\n<p>1.2.1 \u914d\u7f6e\u5907\u4efd\u53c2\u6570<\/p>\n<p>\u5728config\u6587\u4ef6\u5939\u4e0b\u521b\u5efadatabase.php\u6587\u4ef6\uff0c\u8bbe\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u4fe1\u606f\u548c\u5907\u4efd\u6240\u9700\u53c2\u6570\u3002<\/p>\n<pre>&lt;?php return [\n    \/\/ \u6570\u636e\u5e93\u7c7b\u578b\n    'type'        =&gt; 'mysql',\n    \/\/ \u6570\u636e\u5e93\u8fde\u63a5DSN\u914d\u7f6e\n    'dsn'         =&amp;gt; '',\n    \/\/ \u670d\u52a1\u5668\u5730\u5740\n    'hostname'    =&amp;gt; 'localhost',\n    \/\/ \u6570\u636e\u5e93\u540d\n    'database'    =&amp;gt; 'test',\n    \/\/ \u6570\u636e\u5e93\u7528\u6237\u540d\n    'username'    =&amp;gt; 'root',\n    \/\/ \u6570\u636e\u5e93\u5bc6\u7801\n    'password'    =&amp;gt; 'root',\n    \/\/ \u6570\u636e\u5e93\u8fde\u63a5\u7aef\u53e3\n    'hostport'    =&amp;gt; '3306',\n    \/\/ \u6570\u636e\u5e93\u8fde\u63a5\u53c2\u6570\n    'params'      =&amp;gt; [],\n    \/\/ \u6570\u636e\u5e93\u7f16\u7801\u9ed8\u8ba4\u91c7\u7528utf8\n    'charset'     =&amp;gt; 'utf8',\n    \/\/ \u6570\u636e\u5e93\u8868\u524d\u7f00\n    'prefix'      =&amp;gt; 'think_',\n    \/\/ \u6570\u636e\u5e93\u8c03\u8bd5\u6a21\u5f0f\n    'debug'       =&amp;gt; false,\n    \/\/ \u6570\u636e\u5e93\u5907\u4efd\u8def\u5f84\uff0c\u6ca1\u6709\u5219\u81ea\u52a8\u521b\u5efa\n    'path'        =&amp;gt; '',\n    \/\/ \u6570\u636e\u5e93\u5907\u4efd\u5377\u5927\u5c0f\uff0c\u5355\u4f4d\u4e3a\u5b57\u8282\uff0c\u8bbe\u4e3a0\u8868\u793a\u4e0d\u9650\u5236\u5907\u4efd\u5927\u5c0f\n    'part'        =&amp;gt; 20971520,\n    \/\/ \u6570\u636e\u5e93\u5907\u4efd\u6587\u4ef6\u538b\u7f29\u683c\u5f0f\uff0c\u8fd9\u91cc\u662fgzip\n    'compress'    =&amp;gt; 'gzip',\n    \/\/ \u6570\u636e\u5e93\u5907\u4efd\u6587\u4ef6\u540d\n    'filename'    =&amp;gt; '',\n    \/\/ \u6570\u636e\u5e93\u5907\u4efd\u6587\u4ef6\u662f\u5426\u9700\u8981\u538b\u7f29\n    'zip'         =&amp;gt; true,\n    \/\/ \u6570\u636e\u5e93\u5907\u4efd\u6587\u4ef6\u662f\u5426\u9700\u8981\u5206\u5377\u5907\u4efd\n    'split'       =&amp;gt; true,\n    \/\/ \u6570\u636e\u5e93\u5907\u4efd\u65f6\u662f\u5426\u5c06\u5b58\u50a8\u8fc7\u7a0b\u548c\u89e6\u53d1\u5668\u4e00\u8d77\u5907\u4efd\n    'level'       =&amp;gt; 9,\n    \/\/ \u6570\u636e\u5e93\u5907\u4efd\u6587\u4ef6\u7684\u5b58\u50a8\u8def\u5f84\uff0c\u6700\u597d\u4e3a\u7edd\u5bf9\u8def\u5f84\uff0c\u8fd9\u4e5f\u662f\u6700\u5173\u952e\u7684\u8def\u5f84\n    'path'        =&amp;gt; '\/data\/mysql\/',\n];<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>1.2.2 \u7f16\u5199\u5907\u4efd\u4ee3\u7801<\/p>\n<p>\u5728app\/controller\u4e0b\u521b\u5efaBackupController.php\u6587\u4ef6\uff0c\u5e76\u6dfb\u52a0\u4ee5\u4e0b\u4ee3\u7801\u3002<\/p>\n<pre>acadeDb;\n\nclass BackupController\n{\n    protected $backupConfig;\n\n    public function __construct()\n    {\n        $this-&amp;gt;backupConfig = config('database');\n    }\n\n    public function backup()\n    {\n        \/\/ \u9632\u6b62\u5907\u4efd\u6570\u636e\u8fc7\u7a0b\u8d85\u65f6\n        set_time_limit(0);\n\n        $database = $this-&amp;gt;backupConfig['database'];\n        $filename = date('Ymd-His', time()) . \".sql\";\n        $path = $this-&amp;gt;backupConfig['path'].$filename;\n\n        \/\/ \u68c0\u67e5\u76ee\u5f55\u662f\u5426\u5b58\u5728\u6216\u8005\u662f\u5426\u6709\u6743\u9650\u5199\u5165\n        if(!is_dir($this-&amp;gt;backupConfig['path'])){\n            mkdir($this-&amp;gt;backupConfig['path'], 0755, true);\n        }else{\n            if(!is_writeable($this-&amp;gt;backupConfig['path'])){\n                chmod($this-&amp;gt;backupConfig['path'], 0755);\n            }\n        }\n\n        \/\/ \u5907\u4efd\u6240\u6709\u6570\u636e\u8868\n        $result = Db::query(\"SHOW TABLES\");\n\n        $tables = array();\n        foreach($result as $index =&amp;gt; $row){\n            $tables[] = $row['Tables_in_'.$database];\n        }\n\n        \/\/ \u5907\u4efd\u6240\u6709\u8868\u7ed3\u6784\u548c\u8868\u6570\u636e\n        $content = '';\n        foreach($tables as $table){\n            $content = $content . \"\/*\" . PHP_EOL;\n            $content = $content . \"\u8868\u540d\uff1a\" . $table . PHP_EOL;\n            $content = $content . \"\u8868\u7ed3\u6784\uff1a\" . PHP_EOL;\n            $content = $content . \"*\/\" . PHP_EOL;\n            $content = $content . $this-&amp;gt;backupTableSchema($table);\n            $content = $content . \"\/*\" . PHP_EOL;\n            $content = $content . \"\u8868\u6570\u636e\uff1a\" . PHP_EOL;\n            $content = $content . \"*\/\" . PHP_EOL;\n            $content = $content . $this-&amp;gt;buildInsertSql($table);\n        }\n\n        \/\/ \u662f\u5426\u9700\u8981\u538b\u7f29\n        if ($this-&amp;gt;backupConfig['zip']) {\n            $zip = new ZipArchive();\n            $zipfilename = $this-&amp;gt;backupConfig['path'] . date('Ymd-His', time()) . \".zip\";\n            if ($zip-&amp;gt;open($zipfilename, ZipArchive::OVERWRITE) === TRUE) {\n                $zip-&amp;gt;addFile($path,$filename);\n                $zip-&amp;gt;close();\n                \/\/ \u5220\u9664\u975e\u538b\u7f29\u7684\u6587\u4ef6\n                unlink($path);\n            } else {\n                \/\/ \u5907\u4efd\u5931\u8d25\n            }\n        }\n    }\n\n    \/\/ \u5907\u4efd\u8868\u7ed3\u6784\n    protected function backupTableSchema($table)\n    {\n        $database = $this-&amp;gt;backupConfig['database'];\n        $result = Db::query(\"SHOW CREATE TABLE `\" . $table . \"`\");\n        $create = $result[0]['Create Table'] . \";\" . PHP_EOL.PHP_EOL;\n        return $create;\n    }\n\n    \/\/ \u5907\u4efd\u8868\u6570\u636e\n    protected function buildInsertSql($table)\n    {\n        $database = $this-&amp;gt;backupConfig['database'];\n        $result = Db::query(\"SELECT * FROM `\" . $table . \"`\");\n        $insert = '';\n        foreach ($result as $key =&amp;gt; $value) {\n            $keys = array_keys($value);\n            $values = array_map(array(Db::class, 'quote'), array_values($value));\n            $values = join(\",\", $values);\n            $insert .= \"INSERT INTO `\" . $table . \"` (`\" . join(\"`,`\", $keys) . \"`) VALUES (\" . $values . \");\" . PHP_EOL;\n        }\n        $insert .= PHP_EOL;\n        return $insert;\n    }\n}<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>1.2.3 \u6267\u884c\u5907\u4efd<\/p>\n<p>\u5728\u6d4f\u89c8\u5668\u4e2d\u8f93\u5165\u4ee5\u4e0burl\u5730\u5740\u5373\u53ef\u6267\u884c\u5907\u4efd\uff1a<\/p>\n<pre>http:\/\/localhost\/backup\/backup<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>1.3 \u6570\u636e\u5e93\u6062\u590d<\/p>\n<p>1.3.1 \u7f16\u5199\u6062\u590d\u4ee3\u7801<\/p>\n<p>\u5728app\/controller\u4e0b\u521b\u5efaRecoveryController.php\u6587\u4ef6\uff0c\u5e76\u6dfb\u52a0\u4ee5\u4e0b\u4ee3\u7801\u3002<\/p>\n<pre>acadeDb;\n\nclass RecoveryController\n{\n    protected $backupConfig;\n\n    public function __construct()\n    {\n        $this-&amp;gt;backupConfig = config('database');\n    }\n\n    public function recovery()\n    {\n        \/\/ \u9632\u6b62\u8fd8\u539f\u6570\u636e\u8fc7\u7a0b\u8d85\u65f6\n        set_time_limit(0);\n        ini_set('memory_limit', '1024M');\n\n        $filename = input('get.filename');\n\n        \/\/ \u8bfb\u53d6\u5907\u4efd\u6587\u4ef6\n        if ($this-&amp;gt;backupConfig['zip']) {\n            $zip = new ZipArchive();\n            if ($zip-&amp;gt;open($this-&amp;gt;backupConfig['path'].$filename) === true) {\n                $filename = $zip-&amp;gt;getNameIndex(0);\n                $zip-&amp;gt;extractTo($this-&amp;gt;backupConfig['path']);\n                $zip-&amp;gt;close();\n            }\n        }\n\n        $content = file_get_contents($this-&amp;gt;backupConfig['path'] . $filename);\n\n        \/\/ \u4f7f\u7528\";\"\u5206\u5272\u5185\u5bb9\n        $statements = explode(\";\", $content);\n\n        \/\/ \u5f00\u59cb\u4e8b\u52a1\n        Db::startTrans();\n\n        foreach ($statements as $index =&amp;gt; $stmt) {\n            if (trim($stmt) === '') {\n                continue;\n            }\n            $results = Db::query($stmt);\n            if ($results === false) {\n                Db::rollback();\n                return false;\n            }\n        }\n\n        \/\/ \u63d0\u4ea4\u4e8b\u52a1\n        Db::commit();\n\n        \/\/ \u5220\u9664\u975e\u538b\u7f29\u7684\u6587\u4ef6\n        unlink($this-&amp;gt;backupConfig['path'] . $filename);\n\n        return true;\n    }\n}<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>1.3.2 \u6267\u884c\u6062\u590d<\/p>\n<p>\u5728\u6d4f\u89c8\u5668\u4e2d\u8f93\u5165\u4ee5\u4e0burl\u5730\u5740\u5373\u53ef\u6267\u884c\u6062\u590d\uff1a<\/p>\n<pre>http:\/\/localhost\/recovery\/recovery?filename=20200101-121212.sql.zip<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>\u4ee5\u4e0a\u4e3aThinkPHP6\u5b9e\u73b0\u6570\u636e\u5e93\u5907\u4efd\u4e0e\u6062\u590d\u7684\u5b9e\u73b0\u65b9\u6cd5\uff0c\u8bfb\u8005\u53ef\u4ee5\u5c06\u4ee3\u7801\u5e94\u7528\u5230\u81ea\u5df1\u7684\u9879\u76ee\u4e2d\uff0c\u7075\u6d3b\u8fd0\u7528\u5176\u4e2d\u7684\u6280\u5de7\uff0c\u8ba9\u6211\u4eec\u7684\u4e1a\u52a1\u66f4\u52a0\u5065\u58ee\u53ef\u9760\u3002<\/p>\n<p>\u4ee5\u4e0a\u5c31\u662f\u5982\u4f55\u4f7f\u7528ThinkPHP6\u5b9e\u73b0\u6570\u636e\u5e93\u5907\u4efd\u4e0e\u6062\u590d\u7684\u8be6\u7ec6\u5185\u5bb9\uff0c\u66f4\u591a\u8bf7\u5173\u6ce8\u7c73\u4e91\u5176\u5b83\u76f8\u5173\u6587\u7ae0\uff01<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u5728\u5f00\u53d1\u4e1a\u52a1\u7cfb\u7edf\u8fc7\u7a0b\u4e2d\uff0c\u6570\u636e\u5e93\u662f\u975e\u5e38\u91cd\u8981\u7684\u4e00\u73af\u3002\u56e0\u6b64\uff0c\u5bf9\u6570\u636e\u5e93\u8fdb\u884c\u5907\u4efd\u548c\u6062\u590d\u662f\u975e\u5e38\u5fc5\u8981\u7684\u64cd\u4f5c\u3002\u672c\u6587\u5c06\u7ed3\u54086\u6846\u67b6\u5b9e\u4f8b\uff0c\u4ecb\u7ecd\u5982\u4f55\u4f7f\u7528thinkphp6\u5b9e\u73b0\u6570\u636e\u5e93\u5907\u4efd\u4e0e\u6062\u590d\u3002 \u4e00\u3001\u6570\u636e\u5e93\u5907\u4efd 1.1 \u73af\u5883\u51c6\u5907 \u5728\u8fdb\u884c\u6570\u636e\u5e93\u5907\u4efd\u4e4b\u524d\uff0c\u9700\u8981\u786e\u8ba4\u5982\u4e0b\u51e0\u70b9\uff1a 1\u3001\u9700\u8981\u8bbe\u7f6e\u597dmysql\u6570\u636e\u5e93\u7684bin\u76ee\u5f55\u5730\u5740\uff0c\u5e76\u628a\u5176\u8def\u5f84\u52a0\u5165\u7cfb\u7edfPath\u53d8\u91cf\u4e2d\uff1b \u7acb\u5373\u5b66\u4e60\u201c\u201d\uff1b \u70b9\u51fb\u4e0b\u8f7d\u201c\u201d\uff1b 2\u3001\u9700\u8981\u5b89\u88c5\u597dmysqldump\u547d\u4ee4\u884c\u5de5\u5177\uff1b 3\u3001\u786e\u8ba4\u5728\u6570\u636e\u5e93\u6240\u5728\u7684\u673a\u5668\u4e0a\uff0c\u6267\u884c\u5907\u4efd\u7684\u7528\u6237\uff0c\u6709\u5bf9\u6570\u636e\u5e93\u6267\u884cmysqldump\u547d\u4ee4\u7684\u6743\u9650\u3002 1.2 \u6570\u636e\u5e93\u5907\u4efd\u5b9e\u73b0 1.2.1 \u914d\u7f6e\u5907\u4efd\u53c2\u6570 \u5728config\u6587\u4ef6\u5939\u4e0b\u521b\u5efadatabase.php\u6587\u4ef6\uff0c\u8bbe\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u4fe1\u606f\u548c\u5907\u4efd\u6240\u9700\u53c2\u6570\u3002 &lt;?php return [ \/\/ \u6570\u636e\u5e93\u7c7b\u578b &#8216;type&#8217; =&gt; &#8216;mysql&#8217;, \/\/ \u6570\u636e\u5e93\u8fde\u63a5DSN\u914d\u7f6e &#8216;dsn&#8217; =&amp;gt; &#8221;, \/\/ \u670d\u52a1\u5668\u5730\u5740 &#8216;hostname&#8217; =&amp;gt; &#8216;localhost&#8217;, \/\/ \u6570\u636e\u5e93\u540d &#8216;database&#8217; =&amp;gt; &#8216;test&#8217;, \/\/ \u6570\u636e\u5e93\u7528\u6237\u540d &#8216;username&#8217; =&amp;gt; &#8216;root&#8217;, \/\/ \u6570\u636e\u5e93\u5bc6\u7801 &#8216;password&#8217; =&amp;gt; &#8216;root&#8217;, \/\/ \u6570\u636e\u5e93\u8fde\u63a5\u7aef\u53e3 &#8216;hostport&#8217; =&amp;gt; &#8216;3306&#8217;, \/\/ \u6570\u636e\u5e93\u8fde\u63a5\u53c2\u6570 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[16],"tags":[],"class_list":["post-23696","post","type-post","status-publish","format-standard","hentry","category-16"],"_links":{"self":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts\/23696","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/comments?post=23696"}],"version-history":[{"count":0,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts\/23696\/revisions"}],"wp:attachment":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/media?parent=23696"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/categories?post=23696"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/tags?post=23696"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}