這個函式可以在 eval() 中使用 -- 它會停止 eval,但不會停止呼叫 eval() 的腳本。
(PHP 5 >= 5.1.0, PHP 7, PHP 8)
__halt_compiler — 停止編譯器執行
停止編譯器的執行。這對於在 PHP 腳本中嵌入數據,例如安裝檔案,非常有用。
數據起始的位元組位置可以由 __COMPILER_HALT_OFFSET__
常數決定,該常數僅在檔案中存在 __halt_compiler() 時才會被定義。
此函式沒有參數。
不回傳任何值。
範例 #1 __halt_compiler() 範例
<?php
// 開啟這個檔案
$fp = fopen(__FILE__, 'r');
// 將檔案指標指向資料
fseek($fp, __COMPILER_HALT_OFFSET__);
// 並輸出它
var_dump(stream_get_contents($fp));
// 腳本執行結束
__halt_compiler(); 安裝資料 (例如. tar, gz, PHP, 等等.)
備註:
__halt_compiler() 只能在最外層的範圍使用。
__halt_compiler 也可用於除錯。如果您需要暫時進行之後會導致錯誤的更改,請使用 __halt_compiler 來防止語法錯誤。例如
<?php
if ( $something ):
print 'something';
endif; // 為了除錯目的將 endif 放在這裡
__halt_compiler();
endif; // endif 的原始位置 -- 如果沒有 __halt_compiler 的話,會產生語法錯誤
?>
如果在被 "include" 或 "require" 的檔案中出現 "__halt_compiler();",則被呼叫的檔案會被視為在 "__halt_compiler();" 處實際截斷。換句話說,"__halt_compiler();" 只會影響它所在的實體檔案,引入它的外部檔案將繼續執行。
Joey,你說 __halt_compiler 的行為很奇怪是錯的。這個結構的工作方式與其他任何內建結構(如 empty 或 isset)完全相同(甚至與函式類似;至少在 tokenizer 層級)。
關於 T_OPEN_TAG - 在一個 open tag 出現後,您不會期望在目前的 php 代碼區段中出現另一個 open tag,因此 tokenizer 會嘗試以其他方式處理這個「東西」,這是完全正常的...
請注意,如果從 pharstub 使用 __HALT_COMPILER(),則必須為大寫:https://php.dev.org.tw/manual/en/phar.fileformat.stub.php
我不太清楚 PHP 內部是如何運作的,但我不理解在 `token_get_all` 中處理 `__halt_compiler` 的邏輯。
這實際上是有效的:
__halt_compiler/**/ /**/ /**/ /**/ /** */();raw
通常它會跳過任何三個 token,所以即使在 `token_get_all` 中出現 `__halt_compiler***`、`__halt_compiler)))` 等也是可以的。
奇怪的是,它也會跳過 `T_OPEN_TAG`,但在 `__halt_compiler` 運行的上下文中,這個標籤應該不可能出現。相反,它會將 < 和 ? 識別為運算子,而將 php 識別為 `T_STRING`。
它會忽略任何位置的 token,所以以下寫法也是有效的:
__halt_compiler()/**/ /**/ /**/ /**/ /** */;raw
當我使用 php 檔案而不是 tokenizer 進行測試時,結果相同。
我只能得出結論,PHP/`__halt_compiler` 的行為很奇怪。
我認為這是試圖弱模仿函數中相同的語法處理方式(我猜你可以在任何地方放置註釋/空格)。不過,我覺得這很煩人且適得其反。
即使這樣也是有效的:
__halt_compiler// comment\n();raw
複合事項的一個普遍問題是,tokenizer 不會檢查語法是否有效(token 之間的關係)。當作為 PHP 運行時,你必須要有 ();。
如果你發現 `__COMPILER_HALT_OFFSET__` 的值非常奇怪,也許……
有一些編譯器優化工具,例如 eAccelator(非常舊)。當程式被預編譯並快取時,`__COMPILER_HALT_OFFSET__` 將會是 0。