問題は既存のコード本体をフォーマットすることなので、IDE は必要ありません。すべてのファイルを一度にバッチ処理するためのスクリプトが必要です。その後は忘れて構いません。これは、スクリプトが行う必要があることです。
- あらゆる種類の埋め込みまたはエスケープされた引用符を含む文字列を含むPHP文字列を正しく解析します。これは防弾であるべきで、PHP 構文のみを考慮すべきです。
- SQL コマンドを検出するアルゴリズムを使用して、各 PHP 文字列をチェックします。これは、必要なだけ賢くすることができます (たとえば、「挿入」という単語を含むすべての文字列をやみくもに受け入れる必要はありません)。
- 識別された文字列を 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 # global, so that is_sql_string() can examine it
def chunk(src):
"""Chunk the php file into interesting units"""
global php_mode
while src:
if not php_mode: # Read up to the next php group, if any
m = re.match(r".*?<\?php", src, re.S)
if m:
tok, src = _usematch(m, src)
yield tok
php_mode = True
else: # No more php groups: EOF
yield src
return
else: # Reading php code
# PHP ends without another string?
m = re.match(r"[^'\"]*?\?>", src, re.S)
if m:
tok, src = _usematch(m, src)
yield tok
php_mode = False
continue
# at non-string material?
m = re.match(r"[^'\"]+", src)
if m:
tok, src = _usematch(m, src)
yield tok
continue
# Parse a string: Smallest quote-delimited sequence,
# where closing quote is not preceded by backslash
m = re.match(r'".*?(?<!\\)"|' + r"'.*?(?<!\\)'", src, re.S)
if m:
tok, src = _usematch(m, src)
yield tok
continue
# Something I can't parse: advance one char and hope for the best
tok, src = src[0], src[1:]
yield tok
def _usematch(m, inp):
return m.group(), inp[m.end():] # Matched chunk & remaining input
# To recognize an sql command, it MUST begin with one of these words
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)