新增备份
This commit is contained in:
parent
dacf005117
commit
e35a76a80e
@ -50,6 +50,23 @@ class CatchAdmin
|
|||||||
return $directory;
|
return $directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备份地址
|
||||||
|
*
|
||||||
|
* @time 2019年12月13日
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function backupDirectory(): string
|
||||||
|
{
|
||||||
|
$directory = root_path('database/backup');
|
||||||
|
|
||||||
|
if (!is_dir($directory) && !mkdir($directory, 0777, true) && !is_dir($directory)) {
|
||||||
|
throw new \RuntimeException(sprintf('Directory "%s" was not created', $directory));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $directory;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @time 2019年12月03日
|
* @time 2019年12月03日
|
||||||
|
@ -8,6 +8,8 @@ abstract class CatchController
|
|||||||
{
|
{
|
||||||
protected $middleware = ['check_auth'];
|
protected $middleware = ['check_auth'];
|
||||||
|
|
||||||
|
protected $data = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @time 2019年11月28日
|
* @time 2019年11月28日
|
||||||
@ -26,6 +28,10 @@ abstract class CatchController
|
|||||||
'view_path' => CatchAdmin::getViews()[$this->getModule($end['class'])]
|
'view_path' => CatchAdmin::getViews()[$this->getModule($end['class'])]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (!empty($this->data)) {
|
||||||
|
$data = array_merge($this->data, $data);
|
||||||
|
}
|
||||||
|
|
||||||
return View::fetch($template ? : $this->getTemp($end['class'], $end['function']), $data);
|
return View::fetch($template ? : $this->getTemp($end['class'], $end['function']), $data);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -62,4 +68,27 @@ abstract class CatchController
|
|||||||
{
|
{
|
||||||
return explode('\\', $class)[1];
|
return explode('\\', $class)[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @time 2019年12月13日
|
||||||
|
* @param $name
|
||||||
|
* @param $value
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __set($name, $value)
|
||||||
|
{
|
||||||
|
// TODO: Implement __set() method.
|
||||||
|
$this->data[$name] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __get($name)
|
||||||
|
{
|
||||||
|
// TODO: Implement __get() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __isset($name)
|
||||||
|
{
|
||||||
|
// TODO: Implement __isset() method.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@ abstract class CatchModel extends \think\Model
|
|||||||
|
|
||||||
protected $deleteTime = 'deleted_at';
|
protected $deleteTime = 'deleted_at';
|
||||||
|
|
||||||
|
protected $defaultSoftDelete = 0;
|
||||||
|
|
||||||
protected $autoWriteTimestamp = true;
|
protected $autoWriteTimestamp = true;
|
||||||
|
|
||||||
protected $limit = 10;
|
protected $limit = 10;
|
||||||
|
@ -5,7 +5,7 @@ use app\Request;
|
|||||||
use catcher\exceptions\ValidateFailedException;
|
use catcher\exceptions\ValidateFailedException;
|
||||||
use think\Validate;
|
use think\Validate;
|
||||||
|
|
||||||
abstract class CatchRequest extends Request
|
class CatchRequest extends Request
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Request constructor.
|
* Request constructor.
|
||||||
@ -35,8 +35,4 @@ abstract class CatchRequest extends Request
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract protected function rules(): array;
|
|
||||||
|
|
||||||
abstract protected function message(): array;
|
|
||||||
}
|
}
|
||||||
|
@ -1 +1,182 @@
|
|||||||
<?php
|
<?php
|
||||||
|
declare (strict_types = 1);
|
||||||
|
|
||||||
|
namespace catcher\command;
|
||||||
|
|
||||||
|
use catcher\CatchAdmin;
|
||||||
|
use think\Config;
|
||||||
|
use think\console\Command;
|
||||||
|
use think\console\Input;
|
||||||
|
use think\console\input\Argument;
|
||||||
|
use think\console\input\Option;
|
||||||
|
use think\console\Output;
|
||||||
|
use think\facade\Db;
|
||||||
|
|
||||||
|
class BackupCommand extends Command
|
||||||
|
{
|
||||||
|
protected $table;
|
||||||
|
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
// 指令配置
|
||||||
|
$this->setName('backup:data')
|
||||||
|
->addArgument('tables', Argument::REQUIRED, 'backup tables')
|
||||||
|
->addOption('zip', 'z',Option::VALUE_REQUIRED, 'is need zip')
|
||||||
|
->setDescription('backup data you need');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(Input $input, Output $output)
|
||||||
|
{
|
||||||
|
$tables = $this->input->getArgument('tables');
|
||||||
|
|
||||||
|
$isZip = $this->input->getOption('zip') ?? true;
|
||||||
|
|
||||||
|
$this->generator(explode(',', $tables), CatchAdmin::backupDirectory());
|
||||||
|
|
||||||
|
if ($isZip) {
|
||||||
|
$this->zip();
|
||||||
|
}
|
||||||
|
|
||||||
|
$output->info('succeed!');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @time 2019年09月30日
|
||||||
|
* @param $tables
|
||||||
|
* @param $format
|
||||||
|
* @param $path
|
||||||
|
* @return void
|
||||||
|
* @throws \think\db\exception\DbException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
*/
|
||||||
|
public function generator($tables, $path)
|
||||||
|
{
|
||||||
|
foreach ($tables as $table) {
|
||||||
|
$this->table = $table;
|
||||||
|
|
||||||
|
$this->createDataFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建数据文件
|
||||||
|
*
|
||||||
|
* @time 2019年09月27日
|
||||||
|
* @param $format
|
||||||
|
* @return void
|
||||||
|
* @throws \think\db\exception\DbException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
*/
|
||||||
|
public function createDataFile(): void
|
||||||
|
{
|
||||||
|
$file = CatchAdmin::backupDirectory() . $this->table . '.sql';
|
||||||
|
|
||||||
|
$handle = fopen($file, 'wb+');
|
||||||
|
|
||||||
|
fwrite($handle, $begin = "BEGIN;\r\n", \strlen($begin));
|
||||||
|
$this->createClass($this->table, $handle);
|
||||||
|
fwrite($handle, $end = 'COMMIT;', \strlen($end));
|
||||||
|
|
||||||
|
fclose($handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建了临时模型
|
||||||
|
*
|
||||||
|
* @time 2019年09月27日
|
||||||
|
* @param $table
|
||||||
|
* @param $format
|
||||||
|
* @param $handle
|
||||||
|
* @return void
|
||||||
|
* @throws \think\db\exception\DbException
|
||||||
|
* @throws \think\db\exception\ModelNotFoundException
|
||||||
|
* @throws \think\db\exception\DataNotFoundException
|
||||||
|
*/
|
||||||
|
protected function createClass($table, $handle)
|
||||||
|
{
|
||||||
|
$this->setUnbuffered();
|
||||||
|
|
||||||
|
// 防止 IO 多次写入
|
||||||
|
$buffer = [];
|
||||||
|
|
||||||
|
// 记录中记录
|
||||||
|
$total = Db::table($table)->count();
|
||||||
|
|
||||||
|
$limit = 1000;
|
||||||
|
|
||||||
|
// 生成器减少内存
|
||||||
|
while ($total > 0) {
|
||||||
|
$items = Db::table($table)->limit($limit)->select();
|
||||||
|
|
||||||
|
$this->writeIn($handle, $items);
|
||||||
|
|
||||||
|
$total -= $limit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sql 文件格式
|
||||||
|
*
|
||||||
|
* @time 2019年09月27日
|
||||||
|
* @param $handle
|
||||||
|
* @param $data
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function writeIn($handle, $datas)
|
||||||
|
{
|
||||||
|
$values = '';
|
||||||
|
$sql = '';
|
||||||
|
foreach ($datas as $data) {
|
||||||
|
foreach ($data as $value) {
|
||||||
|
$values .= sprintf("'%s'", $value) . ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql .= sprintf('INSERT INTO `%s` VALUE (%s);' . "\r\n", $this->table, rtrim($values, ','));
|
||||||
|
$values = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite($handle, $sql, strlen($sql));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置未缓存模式
|
||||||
|
*
|
||||||
|
* @time 2019年09月29日
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function setUnbuffered()
|
||||||
|
{
|
||||||
|
$connections = \config('database.connections');
|
||||||
|
|
||||||
|
$connections['mysql']['params'] = [
|
||||||
|
\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false
|
||||||
|
];
|
||||||
|
|
||||||
|
\config($connections,'database');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function zip()
|
||||||
|
{
|
||||||
|
if (extension_loaded('zip')) {
|
||||||
|
$files = glob(CatchAdmin::backupDirectory() . '*.sql');
|
||||||
|
$zip = new \ZipArchive();
|
||||||
|
$zip->open(root_path('database/') . 'backup.zip', \ZipArchive::CREATE);
|
||||||
|
$zip->addEmptyDir('backup');
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$zip->addFile($file, 'backup/'. basename($file));
|
||||||
|
}
|
||||||
|
$zip->close();
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
unlink($file);
|
||||||
|
}
|
||||||
|
rmdir(CatchAdmin::backupDirectory());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user