PHP 5.3+ 內建 php_strip_whitespace() 可移除註解與空白,但理解其底層原理有助於建構程式碼分析工具。本文深入解析使用 token_get_all() 實作自定義原始碼壓縮器的完整邏輯。
token_get_all() 將 PHP 原始碼解析為 Token 陣列,每個 Token 為:
;, {, $):字串型態[Token ID, Token 內容, 行號] 陣列<?php
/**
* 移除 PHP 原始碼中的註解與多餘空白
*
* @param string $source PHP 原始碼字串
* @return string 處理後的精簡程式碼
*/
function stripWhitespace($source) {
$output = '';
$tokens = token_get_all($source);
$lastWasWhitespace = false;
for ($i = 0, $count = count($tokens); $i < $count; $i++) {
$token = $tokens[$i];
// 簡單符號:直接輸出
if (is_string($token)) {
$lastWasWhitespace = false;
$output .= $token;
continue;
}
// 複合 Token: [$id, $content, $line]
list($id, $content) = $token;
switch ($id) {
// 1. 過濾註解
case T_COMMENT: // // 註解、/* 註解 */
case T_DOC_COMMENT: // /** 文件註解 */
// 完全跳過,不輸出任何內容
break;
// 2. 處理空白字元 (保留單一空格避免語法錯誤)
case T_WHITESPACE: // 空格、Tab、換行
if (!$lastWasWhitespace) {
$output .= ' '; // 壓縮連續空白為單一空格
$lastWasWhitespace = true;
}
break;
// 3. HEREDOC/NOWDOC 處理
case T_START_HEREDOC: // <<< 開始
$output .= "<< 處理
case T_CLOSE_TAG:
$output .= '?>';
$lastWasWhitespace = false;
break;
// 5. 其他 Token:輸出內容
default:
$lastWasWhitespace = false;
$output .= $content;
}
}
return $output;
}
// 測試範例
$code = '<?php
// 這是單行註解
/* 這是多行
註解 */
$a = 1; // 行尾註解
$b = "hello";
/** 文件註解 */
function test() {
return $a + $b;
}
?>';
echo stripWhitespace($code);
/*
輸出:
*/
?>
| 常數 | 代表 | 範例 |
|---|---|---|
| T_COMMENT | 單行/多行註解 | // comment, /* comment */ |
| T_DOC_COMMENT | PHPDoc 註解 | /** comment */ |
| T_WHITESPACE | 空白字元 | 空格、Tab、換行 |
| T_VARIABLE | 變數 | $var |
| T_STRING | 類別/函數/常數名 | echo, MyClass |
| T_CONSTANT_ENCAPSED_STRING | 字串常值 | 'hello', "world" |
| T_START_HEREDOC | Heredoc 開始 | <<<EOF |
| T_END_HEREDOC | Heredoc 結束 | EOF; |
| T_OPEN_TAG | 開啟標記 | <?php |
| T_CLOSE_TAG | 關閉標記 | ?> |
eval, exec 等危險函數調用token_get_all() 結果token_get_all() 的生成器版本 (PHP 8.0+) 避免記憶體峰值<?php
// 內建函數 (PHP 5.3+)
$stripped = php_strip_whitespace(__FILE__);
// 差異:
// 1. php_strip_whitespace() 直接讀取檔案,不支援字串輸入
// 2. 內建函數保留行號資訊 (錯誤追蹤用)
// 3. 自定義實作可控制保留/移除邏輯 (如保留版權註解)
?>
掌握 Tokenizer 機制不僅能實作程式碼壓縮,更是建構現代 PHP 開發工具鏈 (Linter、Formatter、Analyzer) 的基石。