[ACCEPTED]-Php code formatter / beautifier and php beautification in general-editor

Accepted answer
Score: 44

Well here is my very basic and rough script:

#!/usr/bin/php
<?php
class Token {
    public $type;
    public $contents;

    public function __construct($rawToken) {
        if (is_array($rawToken)) {
            $this->type = $rawToken[0];
            $this->contents = $rawToken[1];
        } else {
            $this->type = -1;
            $this->contents = $rawToken;
        }
    }
}

$file = $argv[1];
$code = file_get_contents($file);

$rawTokens = token_get_all($code);
$tokens = array();
foreach ($rawTokens as $rawToken) {
    $tokens[] = new Token($rawToken);
}

function skipWhitespace(&$tokens, &$i) {
    global $lineNo;
    $i++;
    $token = $tokens[$i];
    while ($token->type == T_WHITESPACE) {
        $lineNo += substr($token->contents, "\n");
        $i++;
        $token = $tokens[$i];
    }
}

function nextToken(&$j) {
    global $tokens, $i;
    $j = $i;
    do {
        $j++;
        $token = $tokens[$j];
    } while ($token->type == T_WHITESPACE);
    return $token;
}

$OPERATORS = array('=', '.', '+', '-', '*', '/', '%', '||', '&&', '+=', '-=', '*=', '/=', '.=', '%=', '==', '!=', '<=', '>=', '<', '>', '===', '!==');

$IMPORT_STATEMENTS = array(T_REQUIRE, T_REQUIRE_ONCE, T_INCLUDE, T_INCLUDE_ONCE);

$CONTROL_STRUCTURES = array(T_IF, T_ELSEIF, T_FOREACH, T_FOR, T_WHILE, T_SWITCH, T_ELSE);
$WHITESPACE_BEFORE = array('?', '{', '=>');
$WHITESPACE_AFTER = array(',', '?', '=>');

foreach ($OPERATORS as $op) {
    $WHITESPACE_BEFORE[] = $op;
    $WHITESPACE_AFTER[] = $op;
}

$matchingTernary = false;

// First pass - filter out unwanted tokens
$filteredTokens = array();
for ($i = 0, $n = count($tokens); $i < $n; $i++) {
    $token = $tokens[$i];
    if ($token->contents == '?') {
        $matchingTernary = true;
    }
    if (in_array($token->type, $IMPORT_STATEMENTS) && nextToken($j)->contents == '(') {
        $filteredTokens[] = $token;
        if ($tokens[$i + 1]->type != T_WHITESPACE) {
            $filteredTokens[] = new Token(array(T_WHITESPACE, ' '));
        }
        $i = $j;
        do {
            $i++;
            $token = $tokens[$i];
            if ($token->contents != ')') {
                $filteredTokens[] = $token;
            }
        } while ($token->contents != ')');
    } elseif ($token->type == T_ELSE && nextToken($j)->type == T_IF) {
        $i = $j;
        $filteredTokens[] = new Token(array(T_ELSEIF, 'elseif'));
    } elseif ($token->contents == ':') {
        if ($matchingTernary) {
            $matchingTernary = false;
        } elseif ($tokens[$i - 1]->type == T_WHITESPACE) {
            array_pop($filteredTokens); // Remove whitespace before
        }
        $filteredTokens[] = $token;
    } else {
        $filteredTokens[] = $token;
    }
}
$tokens = $filteredTokens;

function isAssocArrayVariable($offset = 0) {
    global $tokens, $i;
    $j = $i + $offset;
    return $tokens[$j]->type == T_VARIABLE &&
        $tokens[$j + 1]->contents == '[' &&
        $tokens[$j + 2]->type == T_STRING &&
        preg_match('/[a-z_]+/', $tokens[$j + 2]->contents) &&
        $tokens[$j + 3]->contents == ']';
}

// Second pass - add whitespace
$matchingTernary = false;
$doubleQuote = false;
for ($i = 0, $n = count($tokens); $i < $n; $i++) {
    $token = $tokens[$i];
    if ($token->contents == '?') {
        $matchingTernary = true;
    }
    if ($token->contents == '"' && isAssocArrayVariable(1) && $tokens[$i + 5]->contents == '"') {
        /*
         * Handle case where the only thing quoted is the assoc array variable.
         * Eg. "$value[key]"
         */
        $quote = $tokens[$i++]->contents;
        $var = $tokens[$i++]->contents;
        $openSquareBracket = $tokens[$i++]->contents;
        $str = $tokens[$i++]->contents;
        $closeSquareBracket = $tokens[$i++]->contents;
        $quote = $tokens[$i]->contents;        
        echo $var . "['" . $str . "']";
        $doubleQuote = false;
        continue;
    }
    if ($token->contents == '"') {
        $doubleQuote = !$doubleQuote;
    }
    if ($doubleQuote && $token->contents == '"' && isAssocArrayVariable(1)) {
        // don't echo "
    } elseif ($doubleQuote && isAssocArrayVariable()) {
        if ($tokens[$i - 1]->contents != '"') {
            echo '" . ';
        }
        $var = $token->contents;
        $openSquareBracket = $tokens[++$i]->contents;
        $str = $tokens[++$i]->contents;
        $closeSquareBracket = $tokens[++$i]->contents;
        echo $var . "['" . $str . "']";
        if ($tokens[$i + 1]->contents != '"') {
            echo ' . "';
        } else {
            $i++; // process "
            $doubleQuote = false;
        }
    } elseif ($token->type == T_STRING && $tokens[$i - 1]->contents == '[' && $tokens[$i + 1]->contents == ']') {
        if (preg_match('/[a-z_]+/', $token->contents)) {
            echo "'" . $token->contents . "'";
        } else {
            echo $token->contents;
        }
    } elseif ($token->type == T_ENCAPSED_AND_WHITESPACE || $token->type == T_STRING) {
        echo $token->contents;
    } elseif ($token->contents == '-' && in_array($tokens[$i + 1]->type, array(T_LNUMBER, T_DNUMBER))) {
        echo '-';
    } elseif (in_array($token->type, $CONTROL_STRUCTURES)) {
        echo $token->contents;
        if ($tokens[$i + 1]->type != T_WHITESPACE) {
            echo ' ';
        }
    } elseif ($token->contents == '}' && in_array($tokens[$i + 1]->type, $CONTROL_STRUCTURES)) {
        echo '} ';
    } elseif ($token->contents == '=' && $tokens[$i + 1]->contents == '&') {
        if ($tokens[$i - 1]->type != T_WHITESPACE) {
            echo ' ';
        }
        $i++; // match &
        echo '=&';
        if ($tokens[$i + 1]->type != T_WHITESPACE) {
            echo ' ';          
        }
    } elseif ($token->contents == ':' && $matchingTernary) {
        $matchingTernary = false;
        if ($tokens[$i - 1]->type != T_WHITESPACE) {
            echo ' ';
        }
        echo ':';
        if ($tokens[$i + 1]->type != T_WHITESPACE) {
            echo ' ';
        }
    } elseif (in_array($token->contents, $WHITESPACE_BEFORE) && $tokens[$i - 1]->type != T_WHITESPACE &&
        in_array($token->contents, $WHITESPACE_AFTER) && $tokens[$i + 1]->type != T_WHITESPACE) {
        echo ' ' . $token->contents . ' ';
    } elseif (in_array($token->contents, $WHITESPACE_BEFORE) && $tokens[$i - 1]->type != T_WHITESPACE) {
        echo ' ' . $token->contents;
    } elseif (in_array($token->contents, $WHITESPACE_AFTER) && $tokens[$i + 1]->type != T_WHITESPACE) {
        echo $token->contents . ' ';
    } else {
        echo $token->contents;
    }
}

0

Score: 15

http://en.sourceforge.jp/projects/pdt-tools/

^^^ will give you a proper CTRL+SHIFT+F 2 Eclipse/Aptana PHP formatter like Java.

See 1 here for installation help.

eclipse php code formatter

Score: 13

PHP Code Beautifier is a useful free tool that should do what 4 you're after, although their download page does require 3 an account to be created.

The tool has been 2 declined into 3 versions:

  • A GUI version which allow to process file visually.
  • A command line version which allow to be batched or integrated with other tools (CVS, SubVersion, IDE ...).
  • As an integrated tool of PHPEdit.

Basically, it'll 1 turn:

if($code == BAD){$action = REWRITE;}else{$action = KEEP;}
for($i=0; $i<10;$i++){while($j>0){$j++;doCall($i+$j);if($k){$k/=10;}}}

into

if ($code == BAD) {
    $action = REWRITE;
} else {
    $action = KEEP;
}
for($i = 0; $i < 10;$i++) {
    while ($j > 0) {
        $j++;
        doCall($i + $j);
        if ($k) {
            $k /= 10;
        }
    }
}
Score: 6

There's a pear module that formats your 1 code. PHP Beautifier

Score: 5

If you use Zend Development Environment, you 1 can use the Indent Code feature (Ctrl+Shift+F).

Score: 5

Use NetBeans PHP and press alt+shift+F.

0

Score: 4
Score: 3

The Zend Development Environment is now 7 an Eclipse plugin, you may be able to run 6 it alongside Aptana and just use it's Indent 5 Code feature.

Zend Studio

I haven't upgraded to the 4 Eclipse plugin yet myself, I love the previous 3 ZDE so much. Though now that I've started 2 actually using Eclipse for other languages, I'm 1 almost ready to make the leap.

Score: 2

What about this one:

http://universalindent.sourceforge.net/

It combines a bunch 5 of formatters out there, and will generate 4 the scripts you need so you can pass them 3 out and get your team members to use them 2 before committing next time... Though... formatters 1 might mess up your code and render it unusable...

Score: 2

The simplest solution is to just use an 7 IDE that has this built in. If you're going 6 to be writing code in PHP on a regular a 5 regular basis, just drop the $60 for PHPStorm. You 4 won't regret it.

http://www.jetbrains.com/phpstorm/

It lets you format your 3 code however you like using a simple keyboard 2 shortcut at the file or directory level, and 1 has a zillion other great features.

Score: 1

Our PHP Formatter will reliably format your code. It 4 uses a compiler-based front end to parse 3 the code, so it doesn't misinterpret the 2 code and damage it. Consequently its formatted 1 output always works.

Score: 1

This is an excellent question. I have an 33 application that reads json and outputs 32 php and html and css. I run a program and 31 generate dozens (hundreds?) of files. I 30 hope the answer here is useful.

I started 29 my project using heredocs, special include 28 files, meta chars, etc but that quickly 27 became a mess. I wanted a stand-alone solution 26 that didn't require framework or ide. So 25 I removed all the heredoc and other junk 24 and created a generic text buffering class 23 with no concern for formatting. It can all 22 be one line for all I care. For html, I 21 do tidy() built-in. For php, I use phpstylist. phpstylist 20 is older but still works well for php format.

To 19 set up the phpstylist options I used UniversalIndent (updated 18 Jan 2012) in windows gui.

UniversalStylist 17 lists 24 (!) formatter programs (c, php, ruby, html,...). It 16 specifically knows the options for phpstylist 15 and gives you a live refresh on a file as 14 you turn options on and off. Very great. Then, when 13 you have your style, it has an option to 12 save the command line options and generates 11 a script. For some formatting options you'll 10 have to add paths to perl, python, etc.

If 9 you are using windows and want to try phpstylist 8 with UniversalIndent, just add directory 7 for php.exe to your env path. I use ampps so 6 mine is set to c:\ampps\php.

It was not very 5 easy to find a good solid solution. I'm 4 also interested in hearing what other people 3 do for simple as possible batch formatting 2 of auto-generated php/html files for code 1 review and archiving purposes.

Score: 0

phpformatter.com works best

"This free online PHP Formatter 3 is designed so that you can beautify all 2 your PHP script with the style that you 1 prefer"

More Related questions