Format MySQL code inside PHP string

后端 未结 16 1783
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-02-04 00:29

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

相关标签:
16条回答
  • 2021-02-04 01:30

    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";
    
    0 讨论(0)
  • 2021-02-04 01:31
    1. Log, profile your SQL statements.
    2. Use an external service such as this one - SQLFormat API - in order to format your SQL statements
    3. You can also run it on your machine dowloading the Python sources.
    0 讨论(0)
  • 2021-02-04 01:31

    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:

    1. Correctly parse PHP strings, including strings with all sorts of embedded or escaped quotes. This should be bullet-proof, and should only care about PHP syntax.
    2. Check each PHP string with an algorithm that detects SQL commands. This can be made as smart as you need it to be (no need to blindly accept every string containing the word "insert", for example).
    3. Feed the identified strings through an SQL pretty-printer.
    4. Edit the input file, substituting the formatted string for the original one.

    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)
    
    0 讨论(0)
  • 2021-02-04 01:31

    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

    0 讨论(0)
提交回复
热议问题