PHP Conference Japan 2024

__halt_compiler

(PHP 5 >= 5.1.0, PHP 7, PHP 8)

__halt_compiler 停止編譯器執行

說明

__halt_compiler(): void

停止編譯器的執行。這對於在 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() 只能在最外層的範圍使用。

新增筆記

使用者貢獻的筆記 7 則筆記

-T-
11 年前
這個函式可以在 eval() 中使用 -- 它會停止 eval,但不會停止呼叫 eval() 的腳本。
ravenswd at gmail dot com
14 年前
__halt_compiler 也可用於除錯。如果您需要暫時進行之後會導致錯誤的更改,請使用 __halt_compiler 來防止語法錯誤。例如

<?php
if ( $something ):
print
'something';
endif;
// 為了除錯目的將 endif 放在這裡
__halt_compiler();
endif;
// endif 的原始位置 -- 如果沒有 __halt_compiler 的話,會產生語法錯誤
?>
ravenswd at gmail dot com
8 年前
如果在被 "include" 或 "require" 的檔案中出現 "__halt_compiler();",則被呼叫的檔案會被視為在 "__halt_compiler();" 處實際截斷。換句話說,"__halt_compiler();" 只會影響它所在的實體檔案,引入它的外部檔案將繼續執行。
Krzysiek
10 年前
Joey,你說 __halt_compiler 的行為很奇怪是錯的。這個結構的工作方式與其他任何內建結構(如 empty 或 isset)完全相同(甚至與函式類似;至少在 tokenizer 層級)。

關於 T_OPEN_TAG - 在一個 open tag 出現後,您不會期望在目前的 php 代碼區段中出現另一個 open tag,因此 tokenizer 會嘗試以其他方式處理這個「東西」,這是完全正常的...
alex at 1stleg dot com
4 年前
請注意,如果從 pharstub 使用 __HALT_COMPILER(),則必須為大寫:https://php.dev.org.tw/manual/en/phar.fileformat.stub.php
joey at gimo dot co dot uk
10 年前
我不太清楚 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 運行時,你必須要有 ();。
cwk32 at mail dot ustc dot edu dot cn
9 年前
如果你發現 `__COMPILER_HALT_OFFSET__` 的值非常奇怪,也許……

有一些編譯器優化工具,例如 eAccelator(非常舊)。當程式被預編譯並快取時,`__COMPILER_HALT_OFFSET__` 將會是 0。
To Top