123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475 |
- <?php
- /**
- * 数据库操作 模型
- *
- * session中存放的变量说明:$_SESSION['db_backup']
- * size 文件大小,单位B, 即 传入参数*1024
- * table_name 当前进行备份的表名,即从该表名的位置进行备份,默认为空,即从开头进行备份
- * op 当前表建立动作,create/insert 两种 默认为create
- * limit 条数记录,反映当前insert语句中,处理到的位置,默认为0
- * back_file 备份目录名 格式为YYYYMMDD_序号
- * backup_tables 需要备份的表名列表,为数组格式
- * md5 加密后缀
- *
- */
- defined('InShopNC') or exit('Access Invalid!');
- class dbModel{
- /**
- * 备份语句
- */
- private $back_content = '';
- /**
- * 步骤
- */
- private $step = 1;
- /**
- * 备份数据库
- *
- * @param int $step 步骤
- * @return string 字符类型的返回结果
- */
- public function backUp($step=1){
- $table_list = $_SESSION['db_backup']['backup_tables'];
- if ($step == 1){
- $this->back_content .= "\r\nSET SQL_MODE='NO_AUTO_VALUE_ON_ZERO';\r\n\r\n";
- $_SESSION['db_backup']['table_name'] = $_SESSION['db_backup']['backup_tables'][0];
- }
- $this->step = $step;
- if (!empty($_SESSION['db_backup']['table_name'])){
- $key = array_search($_SESSION['db_backup']['table_name'],$table_list);
- if ($key > 0){
- for ($i=0; $i<$key; $i++){
- unset($table_list[$i]);
- }
- }
- }
- /**
- * 创建表sql
- */
- if ($_SESSION['db_backup']['op'] == 'create'){
- foreach ($table_list as $k => $v){
- /**
- * 写入session
- */
- $_SESSION['db_backup']['table_name'] = $v;
- $result = $this->getCreateContent($v);
- /**
- * 跳出
- */
- if ($result === false){
- return true;
- }
- /**
- * 判断是否最后结束
- */
- if (empty($table_list[$k+1])){
- /**
- * 写入文件
- */
- $this->writeBackFile();
- /**
- * 写入session op
- */
- $_SESSION['db_backup']['op'] = 'insert';
- $_SESSION['db_backup']['table_name'] = $_SESSION['db_backup']['backup_tables'][0];
- return true;
- }
- }
- }
- /**
- * 表信息sql
- */
- if ($_SESSION['db_backup']['op'] == 'insert'){
- foreach ($table_list as $k => $v){
- /**
- * 写入session
- */
- $_SESSION['db_backup']['table_name'] = $v;
- while (true) {
- $result = $this->getInsertContent($v);
- if ($result === 'succ'){
- break;
- }
- /**
- * 跳出
- */
- if ($result === false){
- return true;
- }
- }
- /**
- * 判断是否最后结束
- */
- if (empty($table_list[$k+1]) && $_SESSION['db_backup']['limit'] == 0){
- /**
- * 写入文件
- */
- $this->writeBackFile();
- return true;
- }
- }
- }
- return true;
- }
-
- /**
- * 表名列表
- *
- * @param string $type all/self 取表列表范围,all为整个数据库全部表,self为产品自己的表
- * @return array $rs_row 返回数组形式的查询结果
- */
- public function getTableList($type = 'self'){
- $table_list = array();
- $tmp = Db::showTables();
- $count = strlen(DBPRE);
- $table = "Tables_in_" . DBNAME;
- if ($type == 'all') {
- if (is_array($tmp)) {
- foreach ($tmp as $k => $v) {
- $table_list[] = $v[$table];
- }
- }
- }
- if ($type == 'self') {
- if (is_array($tmp)) {
- foreach ($tmp as $k => $v) {
- $table_list[] = $v[$table];
- }
- }
- }
- return $table_list;
- }
-
-
- /**
- * create表语句内容
- *
- * @param
- * @return string 字符串类型的返回结果
- */
- private function getCreateContent($table){
- /**
- * 构造语句
- */
- $tmp_create = "DROP TABLE IF EXISTS `". $table ."`;\r\n";
- $tmp_create .= Db::showCreateTable(substr($table,strlen(DBPRE),strlen($table)-1));
- $tmp_create .= ";\r\n\r\n";
- /**
- * 判断长度
- */
- if (strlen($this->back_content.$tmp_create) >= $_SESSION['db_backup']['size']){
- /**
- * 写入文件,跳出
- */
- $this->writeBackFile();
- /**
- * 停止备份
- */
- return false;
- }else {
- /**
- * 增加备份语句
- */
- $this->back_content .= $tmp_create;
- /**
- * 继续备份
- */
- return true;
- }
- }
-
- /**
- * 转换特殊符号
- *
- * @param
- * @return string 字符串类型的返回结果
- */
- private function sqlAddslashes($a_string = '', $is_like = false, $crlf = false, $php_code = false){
- if ($is_like) {
- $a_string = str_replace('\\', '\\\\\\\\', $a_string);
- } else {
- $a_string = str_replace('\\', '\\\\', $a_string);
- }
- if ($crlf) {
- $a_string = str_replace("\n", '\n', $a_string);
- $a_string = str_replace("\r", '\r', $a_string);
- $a_string = str_replace("\t", '\t', $a_string);
- }
- if ($php_code) {
- $a_string = str_replace('\'', '\\\'', $a_string);
- } else {
- $a_string = str_replace('\'', '\'\'', $a_string);
- }
- return $a_string;
- }
- /**
- * insert表语句内容
- *
- * @param
- * @return string 字符串类型的返回结果
- */
- private function getInsertContent($table){
- /**
- * 开始条数
- */
- $limit = $_SESSION['db_backup']['limit']?$_SESSION['db_backup']['limit']:0;
- /**
- * 当前语句大小
- */
- $now_size = strlen($this->back_content);
- /**
- * 取信息
- */
- $param = array();
- $param['table'] = substr($table,strlen(DBPRE),strlen($table)-1);
- $param['limit'] = $limit.',300';
- $param['cache'] = false;
- $list = Db::select($param);
- /**
- * 没有信息
- */
- if (empty($list)){
- /**
- * limit数据归0
- */
- $_SESSION['db_backup']['limit'] = 0;
- /**
- * 继续back循环
- */
- return 'succ';
- }
- /**
- * 字段信息
- */
- $columns_array = Db::showColumns(substr($table,strlen(DBPRE),strlen($table)-1));
- /**
- * 生成sql语句
- */
- $result = '';
- foreach ($list as $k => $v){
- $tmp_sql = '';
- $tmp_columns = '';
- $tmp_value = '';
- /**
- * 字段信息
- */
- foreach ($columns_array as $k_col => $v_col){
- /**
- * 字段
- */
- $tmp_columns .= "`". $k_col ."`,";
- /**
- * 值
- */
- if ($v_col['null'] == 'YES'){
- if (empty($v[$k_col])){
- $tmp_value .= "NULL,";
- }else {
- $tmp_value .= "'". $this->sqlAddslashes($v[$k_col]) ."',";
- }
- }else {
- $tmp_value .= "'". $this->sqlAddslashes($v[$k_col]) ."',";
- }
- }
- /**
- * 构造语句
- */
- $tmp_sql .= "INSERT INTO `".$table."` ";
- $tmp_sql .= "(";
- $tmp_sql .= trim($tmp_columns,',');
- $tmp_sql .= ") VALUES(";
- $tmp_sql .= trim($tmp_value,',');
- $tmp_sql .= ")";
- $tmp_sql .= ";\r\n";
- /**
- * 判断字符串大小限制
- */
- if (strlen($this->back_content.$tmp_sql) >= $_SESSION['db_backup']['size']){
- /**
- * 备份文件
- */
- $this->writeBackFile();
- /**
- * 超过限制,跳出讯号
- */
- return false;
- }else {
- /**
- * 增加session中的limit计数
- */
- $_SESSION['db_backup']['limit']++;
- $this->back_content .= $tmp_sql;
- }
- }
-
- /**
- * 结束该表的读取,limit归0
- */
- if (count($list) < 10){
- $_SESSION['db_backup']['limit'] = 0;
- $this->back_content .= "\r\n";
- return 'succ';
- }
- /**
- * 继续back循环
- */
- return true;
- }
-
- /**
- * 获取目录
- *
- * @param
- * @return
- */
- public function getBackDir(){
- /**
- * 按照日期进行生成
- */
- $dir_list = readDirList(BASE_ROOT_PATH.DS.'sql_back');
- $tmp = date('Ymd');
- $check_array = array();
- if (is_array($dir_list)){
- foreach ($dir_list as $k => $v){
- if (substr($v,0,strlen($tmp)) == $tmp){
- $check_array[] = substr($v,strlen($tmp)+1,strlen($v));
- }
- }
- }
- $return = $tmp.'_'.($check_array[count($check_array)-1]+1);
- return $return;
- }
-
- /**
- * 写入文件
- *
- * @param int $id 记录ID
- * @return array $rs_row 返回数组形式的查询结果
- */
- public function writeBackFile(){
- Language::read('model_lang_index');
- $lang = Language::getLangContent();
- $step = $this->step;
- try {
- if (!is_dir(BASE_ROOT_PATH.DS.'sql_back'.DS.$_SESSION['db_backup']['back_file'])){
- if (!$this->mkdirs(BASE_ROOT_PATH.DS.'sql_back'.DS.$_SESSION['db_backup']['back_file'],0755)){
- $error = $lang['db_backup_mkdir_fail'];
- throw new Exception($error);
- }else {
- $fp = @fopen(BASE_ROOT_PATH.DS.'sql_back'.DS.$_SESSION['db_backup']['back_file'].DS.'index.html','w+');
- @fclose($fp);
- }
- }
- $file_name = BASE_ROOT_PATH.DS.'sql_back'.DS.$_SESSION['db_backup']['back_file'].DS.$_SESSION['db_backup']['back_file'].'_'.$step.'_'.$_SESSION['db_backup']['md5'].'.sql';
- $fp = @fopen($file_name,'w+');
- if (@fwrite($fp,$this->back_content) === false){
- $error = $lang['db_backup_vi_file_fail'];
- throw new Exception($error);
- }
- @fclose($fp);
- }catch (Exception $e){
- showMessage($e->getMessage(),'','exception');
- }
- return true;
- }
- /**
- * 建立多级目录
- *
- * @param string $dir 目录
- * @return true
- */
- public function mkdirs($dir){
- if (!is_dir($dir)) {
- if (!$this->mkdirs(dirname($dir))) {
- return false;
- }
- if (!mkdir($dir, 0777)) {
- return false;
- }
- }
- return true;
- }
- /**
- * 数据库备份导入
- *
- * @param string $path 目录
- * @param int $step 步骤,也是第几个文件
- * @return array $rs_row 返回数组形式的查询结果
- */
- public function import($path,$step=1){
- $dir = BASE_ROOT_PATH.DS.'sql_back'.DS.$path;
- $file_list = array();
- readFileList($dir,$file_list);
- /**
- * 过滤文件
- */
- if (!empty($file_list) && is_array($file_list)){
- foreach ($file_list as $key=>$file_name){
- if (strtolower(substr($file_name,-4)) == '.sql'){
- $tmp_list[] = $file_name;
- }
- }
- $file_list = $tmp_list;
- }
- foreach($file_list as $k=>$v){
- $varr = explode('_',$v);
- $file_list[$k] = $varr['0'].'_'.$varr['1'].'_'.$varr['2'].'_'.$varr['3'].'_'.($k+1).'_'.$varr['5'];
- }
- $file_name = $file_list[$step-1];
- //此处使用is_file来判断该sql文件是否存在,不使用file_exists
- if (is_file($file_name)){
- $handle = @fopen($file_name, "r");
- $tmp_sql = '';
- if ($handle) {
- while (!feof($handle)) {
- $buffer = fgets($handle);
- if (trim($buffer) != ''){
- $tmp_sql .= $buffer;
- if (substr(rtrim($buffer),-1) == ';'){
- if (preg_match('/^(CREATE|ALTER|DROP)\s+(VIEW|TABLE|DATABASE|SCHEMA)\s+/i', ltrim($tmp_sql))){
- //标准的SQL语句,将被执行
- }else if (preg_match('/^(INSERT)\s+(INTO)\s+/i', ltrim($tmp_sql)) && substr(rtrim($buffer),-2) == ');'){
- //标准的SQL语句,将被执行
- }else if (preg_match('/^(SET)\s+SQL_MODE=/i', ltrim($tmp_sql))){
- //SET SQL_MODE 设置,将被执行
- }else{
- //不能组成标准的SQL语句,继续向下一行取内容,直到组成合法的SQL为止
- continue;
- }
- if (!empty($tmp_sql)){
- /**
- * 销毁当前用户Session信息
- */
- if (strpos($tmp_sql,cookie('sess_id')) !== false){
- unset($tmp_sql);
- continue;
- }
- Db::query($tmp_sql,'slave');
- unset($tmp_sql);
- }
- }
- }
- }
- @fclose($handle);
- }
- /**
- * 判断是否还有下个文件
- */
- if (empty($file_list[$step])){
- return 'succ';
- }else {
- return 'continue';
- }
- }else {
- return false;
- }
- }
- }
|