【问题标题】:Php code formatter / beautifier and php beautification in general [closed]php代码格式化程序/美化器和一般的php美化[关闭]
【发布时间】:2008-09-29 16:53:53
【问题描述】:

你知道有什么好的工具可以很好地格式化凌乱的 php 代码吗?最好是 Aptana/Eclipse 的脚本,但也可以使用独立工具。

【问题讨论】:

标签: php editor


【解决方案1】:

这是我非常基本和粗略的脚本:

#!/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;
    }
}

【讨论】:

  • 既然可以编写自己的工具,为什么还要使用现有的、经过测试的工具? +1 用 php 编写。
  • 什么?你真的写了吗?
  • 是的,我写了我自己的原因,我找不到任何我满意的现有内容。
  • 有人能把它变成一个 Eclipse 插件吗?
  • 你用它来格式化你的格式化源吗? :-)
【解决方案2】:

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

^^^ 会给你一个合适的 CTRL+SHIFT+F Eclipse/Aptana PHP 格式化程序,比如 Java。

有关安装帮助,请参阅here

【讨论】:

  • 安装说明链接不再可用
  • 刚刚加载对我来说很好。页面标题为“Aptana and Eclispe - Code Formatter for PHP Development Tools for Eclipse”。
  • 该项目在 sourceforge 上似乎已经死了。你知道我现在可以在哪里吗?
【解决方案3】:

PHP Code Beautifier 是一个有用的免费工具,应该可以满足您的需求,尽管他们的download page 确实需要创建一个帐户。

该工具已被拒绝为 3 个版本:

  • 允许可视化处理文件的 GUI 版本。
  • 允许批处理或与其他工具(CVS、SubVersion、IDE ...)集成的命令行版本。
  • 作为 PHPEdit 的集成工具。

基本上,它会转:

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;}}}

进入

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;
        }
    }
}

【讨论】:

  • FWIW,这似乎是一个闭源应用程序,不适用于 Mac OS X。
  • 这对任何人都有效吗?我在格式良好的脚本上尝试了示例命令行,它产生了非常不均匀的缩进:每个函数的第一行有 8 个空格,但其余行有 8 或 9 个空格(似乎是随机的)。另外,函数的右大括号总是缩进 9 个空格。
  • 我可以确认。它创建的代码需要用另一种工具再次格式化:|
  • 请注意:此“工具”已过时、不受支持且不是开源的!
  • PHP Code Beautifier 的链接失效
【解决方案4】:

有一个 pear 模块可以格式化您的代码。 PHP Beautifier

【讨论】:

  • 这看起来很有希望,但我无法让大多数选项起作用(例如,类/函数大括号位置和换行符)。此外,它还删除了 all 空行,即使在函数和类属性之间也是如此,而且我看不到 NewLines 过滤器的标记列表。这个项目有邮件列表吗?
  • 后来我发现它正在咀嚼空白行。 =(
  • 嗯,好在:它是FOSS,所以你可以根据自己的喜好扩展它。
【解决方案5】:

如果您使用 Zend 开发环境,您可以使用缩进代码功能 (Ctrl+Shift+F)。

【讨论】:

  • 也包含在 Eclipse 中
【解决方案6】:

使用 NetBeans PHP 并按 alt+shift+F。

【讨论】:

    【解决方案7】:

    这是一个php代码美化器(当然是PHP)类:
    http://www.codeassembly.com/A-php-code-beautifier-that-works/

    在线演示:

    http://www.codeassembly.com/examples/beautifier.php

    【讨论】:

    【解决方案8】:

    Zend 开发环境现在是一个 Eclipse 插件,您可以将它与 Aptana 一起运行并使用它的缩进代码功能。

    Zend Studio

    我自己还没有升级到 Eclipse 插件,我非常喜欢以前的 ZDE。虽然现在我已经开始实际将 Eclipse 用于其他语言,但我几乎已经准备好迈出这一步了。

    【讨论】:

      【解决方案9】:

      这个呢:

      http://universalindent.sourceforge.net/

      它结合了一堆格式化程序,并将生成您需要的脚本,这样您就可以将它们传递出去并让您的团队成员在下次提交之前使用它们......虽然......格式化程序可能会弄乱您的代码并使其无法使用......

      【讨论】:

      • 如果代码不可用,使用这个格式化程序有什么意义?
      • 任何自动运行的格式化程序都会有这个风险,所以值得注意
      • 格式化程序不必破坏您的代码。他们必须准确地解析它。那些使用正则表达式“解析”的人通常不会这样做,因此......破损。
      • 它也可能会耗尽内存或遇到异常,或者您可以编写一些解析器不理解的代码(已添加到该语言的更新版本但尚未添加的功能由您的解析器支持)。
      • 格式化程序不太可能耗尽内存;与 100K 行的 PHP 脚本相比,1 GB 的 RAM 也很多。如果你能写出解析器看不懂的代码,那么解析器就是愚蠢的实现;好的不是,好的是关于 PHP 语言设施的最新版本。
      【解决方案10】:

      最简单的解决方案是仅使用内置此功能的 IDE。如果您打算定期用 PHP 编写代码,只需花 60 美元购买 PHPStorm。你不会后悔的。

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

      它允许您在文件或目录级别使用简单的键盘快捷方式来格式化您的代码,并具有数不胜数的其他强大功能。

      【讨论】:

      • 哦,NetBeans 和 Eclipse 也内置了一个,它们都是免费的,所以我真的不明白这个问题的意义......
      【解决方案11】:

      我们的 PHP Formatter 将可靠地格式化您的代码。它使用基于编译器的前端来解析代码,因此它不会误解代码并损坏它。因此,它的格式化输出总是有效。

      【讨论】:

      • 50 美元对于我买之前都不敢尝试的东西来说有点贵。
      • 你可以试试。转到下载页面。
      • “基于编译器的前端”如何神奇地将您从格式化程序代码中的错误中拯救出来?
      • @Cweiske:它没有。但是因为它是为重载使用而设计的,所以它建立在极其坚实的基础上,包括正确捕获词位的机制(尤其是 HTML 文本和字符串文字及其在 PHP 中的复杂语法),以及投入大量精力进行仔细测试.这比一些基于正则表达式和字符串黑客的临时格式化程序可靠得多,后者在遇到字符串和 cmets 等复杂语法时经常出错,其中可能包含看起来像代码的东西。
      • 说哇!!!!!!
      【解决方案12】:

      phpformatter.com 效果最好

      “这个免费的在线 PHP 格式化程序旨在让您可以使用自己喜欢的样式美化所有 PHP 脚本”

      【讨论】:

        【解决方案13】:

        这是一个很好的问题。我有一个读取 json 并输出 php、html 和 css 的应用程序。我运行一个程序并生成数十个(数百个?)文件。希望这里的回答有用。

        我使用 heredocs、特殊的包含文件、元字符等开始了我的项目,但很快就变得一团糟。我想要一个不需要框架或 ide 的独立解决方案。所以我删除了所有的 heredoc 和其他垃圾,并创建了一个通用的文本缓冲类,而不关心格式。对于我所关心的一切,它都可以是一条线。对于 html,我内置了 tidy() 。对于 php,我使用phpstylist。 phpstylist 较旧,但仍然适用于 php 格式。

        为了设置 phpstylist 选项,我在 windows gui 中使用了 UniversalIndent(2012 年 1 月更新)。

        UniversalStylist 列出了 24 个 (!) 格式化程序(c、php、ruby、html、...)。它特别了解 phpstylist 的选项,并在您打开和关闭选项时为您提供文件的实时刷新。很好。然后,当您拥有自己的风格时,它可以选择保存命令行选项并生成脚本。对于某些格式化选项,您必须添加 perl、python 等的路径。

        如果您使用的是 windows 并想尝试使用 UniversalIndent 的 phpstylist,只需将 php.exe 的目录添加到您的 env 路径。我使用ampps,所以我的设置为 c:\ampps\php。

        找到一个好的固溶体并不容易。我也有兴趣了解其他人如何对自动生成的 php/html 文件进行尽可能简单的批处理格式化以进行代码审查和归档。

        【讨论】:

          【解决方案14】:

          我也一直在为 PHP 寻找一个像样的免费格式化程序时遇到很多麻烦,有很多在线和命令行工具,但由于某种原因它们似乎不起作用,结果仍然是完整的使用制表符和空格的组合缩进不好,他们永远不会按照你想要的方式得到大括号!

          我尝试了上面的 sn-p,但这对我也不起作用,缩进仍然充满了空格和制表符。

          所以我也尝试过写一个简单的,这个只是使用所有正则表达式,没有花哨的编译器魔法,所以它可能会破坏一些东西,并且仍然是测试版,并且正在对各种混乱的代码进行测试.该界面目前也非常基本,但应该会在接下来的几天内改进。

          对于 MediaWiki 的约定,它是硬连线的,但您可以很容易地对其进行修改(我以后可能会添加选项)。

          https://www.organicdesign.co.nz/Special:CodeTidy

          【讨论】:

            猜你喜欢
            • 2010-09-17
            • 2011-09-03
            • 2012-09-29
            • 2017-04-19
            • 2010-10-24
            • 2018-12-22
            • 2011-04-23
            • 2010-11-03
            相关资源
            最近更新 更多