Is there any program IDE or not that can format MySQL code inside PHP string e.g. I use PHPStorm IDE and it cannot do it.
It does that for PHP and MYSQL but not for MYS
The best way to do this in my opinion is to use Regular Expressions or SED/AWK to format everything, it gives us the bonus of replacement maps on the fly. The chance that you might have code errors though is high, so it's kind of tough.
let me work on it a bit and I can see if I can come up with a good solution. Is it guaranteed that you are encapsulating all SQL in double quotes?
EDIT
Try this
cd {{directory}} && find . -type f -print0 |
xargs -0 perl -i.bak -pe 's/select/SELECT/g ; s/from/\n\tFROM/g ; s/where/\n\t\tWHERE/g ; s/and/\n\t\tAND/g ; s/order by/\n\t\tORDER BY/g ; s/asc/ASC/g ; s/desc/DESC/g ;'
Here's an example
$ printf '"select * from whatever where this = that and active = 1 order by something asc";\n' |
> perl -pe 's/select/SELECT/g ; s/from/\n\tFROM/g ; s/where/\n\t\tWHERE/g ; s/and/\n\t\tAND/g ; s/order by/\n\t\tORDER BY/g ; s/asc/ASC/g ; s/desc/DESC/g ;'
"SELECT *
FROM whatever
WHERE this = that
AND active = 1
ORDER BY something ASC";
Is it pretty? no, not at all, does it work.... Yeup.
I'll try creating a filter file and maybe a little bash program or something as i get time to run this hot mess.
EDIT
Here's some revised code, looks prettier (sorta)
printf '$request1 = "select * from whatever where this = that and active = 1 order by something asc";\n' |
perl -pe 's/select/SELECT/gi ; s/from/\n FROM/gi ; s/where/\n WHERE/gi ; s/and/\n AND/gi ; s/order by/\n ORDER BY/gi ; s/asc/ASC/gi ; s/desc/DESC/gi ;' |
awk 'NR == 1 {pad = length($0)/2; print} NR > 1 {gsub(/\r/,""); printf "%*s%s\n", pad, " ", $0}'
__OUTPUTS__
$request1 = "SELECT *
FROM whatever
WHERE this = that
AND active = 1
ORDER BY something ASC";
Since your problem is to format an existing body of code, you don't need an IDE. You need a script to batch-process all your files once, and then you can forget about it. This is what the script needs to do:
Ideally, parts 1 and 3 should be handled by off-the-shelf modules. The rest should be easy to put together yourself, right?
Update: Explaining this made it sound so simple, I decided to do it myself. Here's a quick solution. It's in python, but if you were willing to switch IDEs you can deal with installing python, right?
Drag-and-drop any number of php files onto the script, or call it from the commandline, and it will filter the SQL bits through the SQLFormat API that @Parahat suggested. It edits the files in place, so keep a copy!
"""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)
In PHPStorm you can specify SQL dialect for your project: http://www.jetbrains.com/phpstorm/webhelp/sql-dialects.html
Next, you must setup Data Source: http://www.jetbrains.com/phpstorm/webhelp/data-sources-2.html
After that your IDE will support SQL syntax and autocomplete for tables (fields).
Also, there is a page, where you can specify SQL code-style: http://www.jetbrains.com/phpstorm/webhelp/code-style-sql.html