当php_strip_whitespace赶上heredoc

时间:2014-02-15所属栏目: PHP/PHP框架 来源: 未知 热度:

php_strip_whitespace首要浸染是去除PHP源码中的回车、换行、空格和注释,到达代码压缩的结果。
可是PHP中heredoc的竣事标志有点犷悍,必需独有一行,容不得除英文分号(;)以外的任何字符。
正确例子:

<?php
$doc = <<<DOC
sometext...
DOC;
echo $doc;
?>


错误例子:

<?php
$doc = <<<DOC
sometext...
DOC;echo $doc;
?>

但当颠末php_strip_whitespace压缩过的代码,也许会酿成以下样子:

<?php
$doc = <<<DOC sometext... DOC;echo $doc;
?>

很明明heredoc的竣事标志就不是独有一行了,它很气愤,效果很严峻,PHP直接报错了。
但现实上,php_strip_whitespace对这段代码是无法压缩的,会报以下错误:

Warning: php_strip_whitespace(<?php
function abc($s){
    $html = <<<HTML
<h1>{$s}</h1>
HTML;
    echo $html;
}
?>): failed to open stream: No such file or directory in C:\Users\hdj\Desktop\demo.php on line 134

虽然,这是php_strip_whitespace对heredoc兼容欠好,算是PHP的bug了,但愿PHP官方能尽快完美。再虽然,并不是代表对付包括heredoc的PHP代码就完全无计可施,个中PHP手册中就有提出办理方案。

<?php
 
function compress_php_src($src) {
     // Whitespaces left and right from this signs can be ignored
     static $IW = array(
         T_CONCAT_EQUAL,             // .=
         T_DOUBLE_ARROW,             // =>
         T_BOOLEAN_AND,              // &&
         T_BOOLEAN_OR,               // ||
         T_IS_EQUAL,                 // ==
         T_IS_NOT_EQUAL,             // != or <>
         T_IS_SMALLER_OR_EQUAL,      // <=
         T_IS_GREATER_OR_EQUAL,      // >=
         T_INC,                      // ++
         T_DEC,                      // --
         T_PLUS_EQUAL,               // +=
         T_MINUS_EQUAL,              // -=
         T_MUL_EQUAL,                // *=
         T_DIV_EQUAL,                // /=
         T_IS_IDENTICAL,             // ===
         T_IS_NOT_IDENTICAL,         // !==
         T_DOUBLE_COLON,             // ::
         T_PAAMAYIM_NEKUDOTAYIM,     // ::
         T_OBJECT_OPERATOR,          // ->
         T_DOLLAR_OPEN_CURLY_BRACES, // ${
         T_AND_EQUAL,                // &=
         T_MOD_EQUAL,                // %=
         T_XOR_EQUAL,                // ^=
         T_OR_EQUAL,                 // |=
         T_SL,                       // <<
         T_SR,                       // >>
         T_SL_EQUAL,                 // <<=
         T_SR_EQUAL,                 // >>=
     );
     if(is_file($src)) {
         if(!$src = file_get_contents($src)) {
             return false;
         }
     }
     $tokens = token_get_all($src);
     
    $new = "";
     $c = sizeof($tokens);
     $iw = false; // ignore whitespace
     $ih = false; // in HEREDOC
     $ls = "";    // last sign
     $ot = null;  // open tag
     for($i = 0; $i < $c; $i++) {
         $token = $tokens[$i];
         if(is_array($token)) {
             list($tn, $ts) = $token; // tokens: number, string, line
             $tname = token_name($tn);
             if($tn == T_INLINE_HTML) {
                 $new .= $ts;
                 $iw = false;
             } else {
                 if($tn == T_OPEN_TAG) {
                     if(strpos($ts, " ") || strpos($ts, "\n") || strpos($ts, "\t") || strpos($ts, "\r")) {
                         $ts = rtrim($ts);
                     }
                     $ts .= " ";
                     $new .= $ts;
                     $ot = T_OPEN_TAG;
                     $iw = true;
                 } elseif($tn == T_OPEN_TAG_WITH_ECHO) {
                     $new .= $ts;
                     $ot = T_OPEN_TAG_WITH_ECHO;
                     $iw = true;
                 } elseif($tn == T_CLOSE_TAG) {
                     if($ot == T_OPEN_TAG_WITH_ECHO) {
                         $new = rtrim($new, "; ");
                     } else {
                         $ts = " ".$ts;
                     }
                     $new .= $ts;
                     $ot = null;
                     $iw = false;
                 } elseif(in_array($tn, $IW)) {
                     $new .= $ts;
                     $iw = true;
                 } elseif($tn == T_CONSTANT_ENCAPSED_STRING
                        || $tn == T_ENCAPSED_AND_WHITESPACE)
                 {
                     if($ts[0] == '"') {
                         $ts = addcslashes($ts, "\n\t\r");
                     }
                     $new .= $ts;
                     $iw = true;
                 } elseif($tn == T_WHITESPACE) {
                     $nt = @$tokens[$i+1];
                     if(!$iw && (!is_string($nt) || $nt == '$') && !in_array($nt[0], $IW)) {
                         $new .= " ";
                     }
                     $iw = false;
                 } elseif($tn == T_START_HEREDOC) {
                     $new .= "<<<S\n";
                     $iw = false;
                     $ih = true; // in HEREDOC
                 } elseif($tn == T_END_HEREDOC) {
                     $new .= "S;";
                     $iw = true;
                     $ih = false; // in HEREDOC
                     for($j = $i+1; $j < $c; $j++) {
                         if(is_string($tokens[$j]) && $tokens[$j] == ";") {
                             $i = $j;
                             break;
                         } else if($tokens[$j][0] == T_CLOSE_TAG) {
                             break;
                         }
                     }
                 } elseif($tn == T_COMMENT || $tn == T_DOC_COMMENT) {
                     $iw = true;
                 } else {
                     if(!$ih) {
                         $ts = strtolower($ts);
                     }
                     $new .= $ts;
                     $iw = false;
                 }
             }
             $ls = "";
         } else {
             if(($token != ";" && $token != ":") || $ls != $token) {
                 $new .= $token;
                 $ls = $token;
             }
             $iw = true;
         }
     }
     return $new;
 }
 
?>
 
For example:
 <?php
 
$src = <<<EOT
 <?php
 // some comment
 for ( $i = 0; $i < 99; $i ++ ) {
    echo "i=${ i }\n";
    /* ... */
 }
 /** ... */
 function abc() {
    return   "abc";
 };
 
abc();
 ?>
 <h1><?= "Some text " . str_repeat("_-x-_ ", 32);;; ?></h1>
 EOT;
 var_dump(compress_php_src($src));
 ?>
标签:
评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)