由于您的问题是格式化现有代码,所以不需要IDE。您需要一个脚本批处理所有文件一次,然后您就可以忘记它了。这是脚本需要执行的操作:
- 正确解析PHP字符串,包括各种嵌入或转义引号的字符串。这应该是牢固可靠的,并且只关心PHP语法。
- 使用检测SQL命令的算法检查每个PHP字符串。这可以智能化,您无需盲目接受每个包含“insert”单词的字符串。
- 将已识别的字符串通过SQL美化程序进行处理。
- 编辑输入文件,用格式化的字符串替换原始字符串。
理想情况下,部分1和3应由现成的模块处理。其余部分应该很容易自己组合起来,对吧?
更新:解释起来很简单,我决定自己做。这是一个快速解决方案。它是用Python编写的,但如果您愿意切换IDE,您可以处理安装Python,对吧?
将任意数量的php文件拖放到脚本上,或从命令行调用它,它将通过@Parahat建议的
SQLFormat API过滤SQL代码。它会直接编辑文件,因此请保留副本!
"""Format sql strings embedded in php code, editing source IN PLACE"""
import sys, re, urllib, urllib2
def processfile(fname):
with open(fname) as fp:
text = fp.read()
with open(fname, "w") as out:
for token in chunk(text):
if is_sql_string(token):
token = token[0] + sqlformat(token[1:-1]) + token[0]
out.write(token)
def sqlformat(query):
sqlapi = 'http://sqlformat.appspot.com/format/?keyword_case=upper&reindent=1&n_indents=4&'
return urllib2.urlopen(sqlapi+urllib.urlencode({'data':query})).read()
php_mode = False
def chunk(src):
"""Chunk the php file into interesting units"""
global php_mode
while src:
if not php_mode:
m = re.match(r".*?<\?php", src, re.S)
if m:
tok, src = _usematch(m, src)
yield tok
php_mode = True
else:
yield src
return
else:
m = re.match(r"[^'\"]*?\?>", src, re.S)
if m:
tok, src = _usematch(m, src)
yield tok
php_mode = False
continue
m = re.match(r"[^'\"]+", src)
if m:
tok, src = _usematch(m, src)
yield tok
continue
m = re.match(r'".*?(?<!\\)"|' + r"'.*?(?<!\\)'", src, re.S)
if m:
tok, src = _usematch(m, src)
yield tok
continue
tok, src = src[0], src[1:]
yield tok
def _usematch(m, inp):
return m.group(), inp[m.end():]
sql_commands = set("select insert update delete create drop alter declare".split())
def is_sql_string(tok):
if not php_mode or len(tok) < 3 or tok[0] not in set("\"'"):
return False
tokwords = tok[1:-1].split()
return tokwords and tokwords[0].lower() in sql_commands
for fname in sys.argv[1:]:
processfile(fname)
mysql_real_string_escape()
来防止SQL注入。 - glglgl