123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- <?php
- namespace app\admin\controller;
- use think\Db;
- use app\common\util\Dir;
- use app\common\util\Database as dbOper;
- class Database extends Base
- {
- var $_db_config;
- public function __construct()
- {
- parent::__construct();
- }
- public function index()
- {
- $group = input('group');
- if($group=='import'){
- //列出备份文件列表
- $path = trim( $GLOBALS['config']['db']['backup_path'], '/').DS;
- if (!is_dir($path)) {
- Dir::create($path);
- }
- $flag = \FilesystemIterator::KEY_AS_FILENAME;
- $glob = new \FilesystemIterator($path, $flag);
- $list = [];
- foreach ($glob as $name => $file) {
- if(preg_match('/^\d{8,8}-\d{6,6}-\d+\.sql(?:\.gz)?$/', $name)){
- $name = sscanf($name, '%4s%2s%2s-%2s%2s%2s-%d');
- $date = "{$name[0]}-{$name[1]}-{$name[2]}";
- $time = "{$name[3]}:{$name[4]}:{$name[5]}";
- $part = $name[6];
- if(isset($list["{$date} {$time}"])){
- $info = $list["{$date} {$time}"];
- $info['part'] = max($info['part'], $part);
- $info['size'] = $info['size'] + $file->getSize();
- } else {
- $info['part'] = $part;
- $info['size'] = $file->getSize();
- }
- $extension = strtoupper($file->getExtension());
- $info['compress'] = ($extension === 'SQL') ? '无' : $extension;
- $info['time'] = strtotime("{$date} {$time}");
- $list["{$date} {$time}"] = $info;
- }
- }
- }
- else{
- $group='export';
- $list = Db::query("SHOW TABLE STATUS");
- }
- $this->assign('list',$list);
- $this->assign('title',lang('admin/database/title'));
- return $this->fetch('admin@database/'.$group);
- }
- public function export($ids = '', $start = 0)
- {
- if ($this->request->isPost()) {
- if (empty($ids)) {
- return $this->error(lang('admin/database/select_export_table'));
- }
- if (!is_array($ids)) {
- $tables[] = $ids;
- } else {
- $tables = $ids;
- }
- $have_admin = false;
- $admin_table='';
- foreach($tables as $k=>$v){
- if(strpos($v,'_admin')!==false){
- $have_admin=true;
- $admin_table = $v;
- unset($tables[$k]);
- }
- }
- if($have_admin){
- $tables[] = $admin_table;
- }
- //读取备份配置
- $config = array(
- 'path' => $GLOBALS['config']['db']['backup_path'] .DS,
- 'part' => $GLOBALS['config']['db']['part_size'] ,
- 'compress' => $GLOBALS['config']['db']['compress'] ,
- 'level' => $GLOBALS['config']['db']['compress_level'] ,
- );
- //检查是否有正在执行的任务
- $lock = "{$config['path']}backup.lock";
- if(is_file($lock)){
- return $this->error(lang('admin/database/lock_check'));
- } else {
- if (!is_dir($config['path'])) {
- Dir::create($config['path'], 0755, true);
- }
- //创建锁文件
- file_put_contents($lock, $this->request->time());
- }
- //生成备份文件信息
- $file = [
- 'name' => date('Ymd-His', $this->request->time()),
- 'part' => 1,
- ];
- // 创建备份文件
- $database = new dbOper($file, $config);
- if($database->create() !== false) {
- // 备份指定表
- foreach ($tables as $table) {
- $start = $database->backup($table, $start);
- while (0 !== $start) {
- if (false === $start) {
- return $this->error(lang('admin/database/backup_err'));
- }
- $start = $database->backup($table, $start[0]);
- }
- }
- // 备份完成,删除锁定文件
- unlink($lock);
- }
- return $this->success(lang('admin/database/backup_ok'));
- }
- return $this->error(lang('admin/database/backup_err'));
- }
- /**
- * 恢复数据库 [参考原作者 麦当苗儿 <[email protected]>]
- * @param string|array $ids 表名
- * @param integer $start 起始行数
- * @author 橘子俊 <[email protected]>
- * @return mixed
- */
- public function import($id = '')
- {
- if (empty($id)) {
- return $this->error(lang('admin/database/select_file'));
- }
- $name = date('Ymd-His', $id) . '-*.sql*';
- $path = trim( $GLOBALS['config']['db']['backup_path'] , '/').DS.$name;
- $files = glob($path);
- $list = array();
- foreach($files as $name){
- $basename = basename($name);
- $match = sscanf($basename, '%4s%2s%2s-%2s%2s%2s-%d');
- $gz = preg_match('/^\d{8,8}-\d{6,6}-\d+\.sql.gz$/', $basename);
- $list[$match[6]] = array($match[6], $name, $gz);
- }
- ksort($list);
- // 检测文件正确性
- $last = end($list);
- if(count($list) === $last[0]){
- foreach ($list as $item) {
- $config = [
- 'path' => trim($GLOBALS['config']['db']['backup_path'], '/').DS,
- 'compress' => $item[2]
- ];
- $database = new dbOper($item, $config);
- $start = $database->import(0);
- // 导入所有数据
- while (0 !== $start) {
- if (false === $start) {
- return $this->error(lang('admin/database/import_err'));
- }
- $start = $database->import($start[0]);
- }
- }
- return $this->success(lang('admin/database/import_ok'));
- }
- return $this->error(lang('admin/database/file_damage'));
- }
- public function optimize($ids = '')
- {
- if (empty($ids)) {
- return $this->error(lang('admin/database/select_optimize_table'));
- }
- if (!is_array($ids)) {
- $table[] = $ids;
- } else {
- $table = $ids;
- }
- $tables = implode('`,`', $table);
- $res = Db::query("OPTIMIZE TABLE `{$tables}`");
- if ($res) {
- return $this->success(lang('admin/database/optimize_ok'));
- }
- return $this->error(lang('admin/database/optimize_err'));
- }
- public function repair($ids = '')
- {
- if (empty($ids)) {
- return $this->error(lang('admin/database/select_repair_table'));
- }
- if (!is_array($ids)) {
- $table[] = $ids;
- } else {
- $table = $ids;
- }
- $tables = implode('`,`', $table);
- $res = Db::query("REPAIR TABLE `{$tables}`");
- if ($res) {
- return $this->success(lang('admin/database/repair_ok'));
- }
- return $this->error(lang('admin/database/repair_ok'));
- }
- public function del($id = '')
- {
- if (empty($id)) {
- return $this->error(lang('admin/database/select_del_file'));
- }
- $name = date('Ymd-His', $id) . '-*.sql*';
- $path = trim($GLOBALS['config']['db']['backup_path']).DS.$name;
- array_map("unlink", glob($path));
- if(count(glob($path)) && glob($path)){
- return $this->error(lang('del_err'));
- }
- return $this->success(lang('del_ok'));
- }
- public function sql()
- {
- if($this->request->isPost()){
- $param=input();
- $validate = \think\Loader::validate('Token');
- if(!$validate->check($param)){
- return $this->error($validate->getError());
- }
- $sql = trim($param['sql']);
- if(!empty($sql)){
- $forbidden_keywords = ['into dumpfile', 'into outfile', 'char(', 'load_file'];
- foreach ($forbidden_keywords as $keyword) {
- if (stripos($sql, $keyword) !== false) {
- return $this->error(lang('format_err'));
- }
- }
- $sql = str_replace('{pre}',config('database.prefix'),$sql);
- //查询语句返回结果集
- if(
- strtolower(substr($sql,0,6))=="select" ||
- stripos($sql, ' outfile') !== false
- ){
- }
- else{
- Db::execute($sql);
- }
- }
- $this->success(lang('run_ok'));
- }
- return $this->fetch('admin@database/sql');
- }
- public function columns()
- {
- $param = input();
- $table = $param['table'];
- if (!empty($table) && !$this->isValidTable($table)) {
- return $this->error('Table is invalid.');
- }
- if (!empty($table)) {
- $list = Db::query('SHOW COLUMNS FROM ' . $table);
- $this->success(lang('obtain_ok'),null, $list);
- }
- $this->error(lang('param_err'));
- }
- public function rep()
- {
- if($this->request->isPost()){
- $param = input();
- $table = $param['table'];
- $field = $param['field'];
- $findstr = $param['findstr'];
- $tostr = $param['tostr'];
- $where = $param['where'];
- $validate = \think\Loader::validate('Token');
- if(!$validate->check($param)){
- return $this->error($validate->getError());
- }
- if (!empty($table) && !$this->isValidTable($table)) {
- return $this->error('Table is invalid.');
- }
- if(!empty($field) && !empty($findstr) && !empty($tostr)){
- $sql = "UPDATE ".$table." set ".$field."=Replace(".$field.",'".$findstr."','".$tostr."') where 1=1 ". $where;
- Db::execute($sql);
- return $this->success(lang('run_ok'));
- }
- return $this->error(lang('param_err'));
- }
- $list = Db::query("SHOW TABLE STATUS");
- $this->assign('list',$list);
- return $this->fetch('admin@database/rep');
- }
- private function isValidTable($table) {
- $list = Db::query("SHOW TABLE STATUS");
- foreach ($list as $table_raw) {
- if ($table_raw['Name'] == $table) {
- return true;
- }
- }
- return false;
- }
- }
|