最近在整理项目的数据库的内容,有两个问题是要解决的,一个问题是有些表已经没有在文件里跑了,我需要筛选掉,一个问题是还在用的那些表,分别是在哪些文件里跑的?
数据表我统计了一下,有200+。项目的控制器文件,当然是两个文件夹,一个关于前台的,一个关于后台的。
然后,逻辑上是这样的,先把sql文件遍历一遍,取出所有表名,再把每个表名去两个文件夹里跑一遍。
写这个程序,有三个头是必不可少的:
header("Content-type: text/html; charset=utf-8"); error_reporting(0); set_time_limit(0);
其实一般都是等到出现问题,再加上这三个头的...
先说说遍历sql文件,取出表名,其实很容易,不过正则表达式我写不好,就用str_replace函数代替了。
function sqlarr($mdir) { $str=file_get_contents($mdir); if(!$str) { echo '<script>';echo 'alert(\'文件路径不存在!\');';echo '</script>';return false; } $pattern = '/表的结构 \`.*\`/isU'; preg_match_all($pattern, $str, $match); $match = array_unique($match[0]); static $arr = array(); foreach ($match as $key => $value) { $value = str_replace("`","",$value); $value = str_replace("表的结构 ","",$value); $v2 = str_replace("head_","",$value); //不能是带日期的错误文件 $w = '/-/isU'; preg_match_all($w,$v2,$mm); if (!$mm[0]) { $arr[] = $v2; } } return $arr; }
$mdir就是sql文件的路径了,因为有些带日期的错误文件,也被我筛选掉了,值得一提,这是phpmyadmin导出来的sql文件,一般是可以用这个方法找出所有表名的。
然后就是将返回的数组进行循环,每个值都对文件进行遍历就行了。
$mSqlArr = sqlarr('URL'); foreach ($mSqlArr as $k => $v) { $k++; echo '<br/><br/><b><font color="green">'.$v.'('.$k.')</font></b><br/><br/>'; listDir("./",$v); }
listDir()就是遍历函数了。这样子,会输出表名和表名的排序。对两百多个表名来说,这个查询过程很久,程序至少需要运行十几分钟。
下一步就是listDir这个递归函数了,这个没什么好说的,写出来调试就可以了,我的代码是这样的:
function listDir($dir,$keyword) { //前台的有效文件 $arrA = array(); //后台的有效文件 $arrB = array(); $a_files = ''; $b_files = ''; if(is_dir($dir)) { if ($dh = opendir($dir)) { while (($file = readdir($dh)) !== false) { if((is_dir($dir."/".$file)) && $file!="." && $file!="..") { if($file == 'Action')echo "<hr><b><font color='red'>Action路径:</font></b>",$dir.$file,"<br/>"; listDir($dir.$file."/",$keyword); } else { $extension=substr(strrchr($file, '.'), 1); //这里加筛选条件 if($file!="." && $file!=".." && $extension='php' ) { $content=file_get_contents($dir.$file); $parameter = 'M(\''.$keyword.'\')'; $match = strpos($content,$parameter); $num = substr_count($content,$parameter); if(!$match) { $con =''; } else { $file = str_replace("Action.class.php","",$file); $con = '文件名:'.$file; $con .= ' 次数:'.$num; //前台 if($dir == './A/Lib/Action/') { if(in_array($file,$arrA)) { $con .= '<b><font color="blue">(有效)</font></b><br/><br/>'; $a_files .= $file.'、'; } else { $con .= '<b><font color="red">(无效)</font></b><br/><br/>'; } } elseif($dir == './B/Lib/Action/') { //后台 if(in_array($file,$arrB)) { $con .= '<b><font color="blue">(有效)</font></b><br/><br/>'; $b_files .= $file.'、'; } else { $con .= '<b><font color="red">(无效)</font></b><br/><br/>'; } } else { $con .= '<b><font color="green">(未知)</font></b><br/><br/>'; } } //file_put_contents('../test.php',$match,FILE_APPEND); print_r($con); ob_flush(); flush(); } } } closedir($dh); } } print_r($a_files); print_r($b_files); return false; }
这个函数的作用,就是让表名到两个文件夹里去循环,输出含有该表名的文件名称了,$arrA和$arrB就是给他判断哪些是有效文件了(有些文件我知道作废了)。
从路径上看可知,这是thinkphp的目录结构,是控制器放置的文件夹。
第一个参数是路径,第二个参数是关键字,也就是表名。
最后,我写了个可以简单查询单独一个表名情况的代码。
$keyword = isset($_POST['keyword'])?$_POST['keyword']:''; //一律小写,删除空格 $keyword = str_replace(' ','',strtolower($keyword)); echo '<form method="post" action="'.GetCurUrl().'" style="position:fixed;top:100px;right:200px;"><input type="text" name="keyword"/><input type="submit" value="搜索表名" /></form>'; echo '搜索的表名:'.$keyword.'<br/>'; if(!$keyword){echo '<script>';echo 'alert(\'不能为空\');';echo '</script>';return false;} //开始运行 listDir("./",$keyword);
这里有个得到当前域名的函数:
function GetCurUrl() { if(!empty($_SERVER["REQUEST_URI"])) { $scriptName = $_SERVER["REQUEST_URI"]; $nowurl = $scriptName; } else { $scriptName = $_SERVER["PHP_SELF"]; if(empty($_SERVER["QUERY_STRING"])) { $nowurl = $scriptName; } else { $nowurl = $scriptName."?".$_SERVER["QUERY_STRING"]; } } return $nowurl; }
最后,就大功告成了。