PHP Conference Japan 2024

exit

(PHP 4, PHP 5, PHP 7, PHP 8)

exit以狀態碼或訊息終止目前的腳本

說明

exit(字串|整數 $status = 0): 永不

終止腳本的執行。即使呼叫了 exit()關閉函式物件解構器 也會被執行。然而,finally 區塊永遠不會被執行。

結束代碼 0 表示程式成功完成其任務。任何其他值都表示在執行期間發生了某種錯誤。

exit() 是一個特殊的函式,因為它在解析器中有一個專用的權杖,因此它可以像語句一樣使用(即不帶括號)以預設狀態碼終止腳本。

注意

無法停用或建立命名空間函式來遮蔽全域的 exit() 函式。

參數

status
如果 status 是一個字串,則此函式會在退出之前印出 status。PHP 返回的結束代碼為 0

如果 status 是一個 int,PHP 返回的結束代碼將是 status

注意事項 結束代碼應在 0254 的範圍內,結束代碼 255 由 PHP 保留,不應使用。

警告

在 PHP 8.4.0 之前,exit() 並未遵循 PHP 標準的 類型轉換語義,也沒有遵守 strict_types 宣告。

任何非 int 類型的值都會被強制轉換為 string 類型,包括 resourcearray 值。從 PHP 8.4.0 開始,它遵循通常的類型轉換語義,並在無效值時拋出 TypeError

返回值

由於這會終止 PHP 腳本,因此不會返回任何值。

更新日誌

版本 說明
8.4.0 exit() 現在是一個正規的函式,因此它遵循通常的 類型轉換語義,會受到 strict_types 宣告的影響,可以通過命名參數調用,並且可以作為 可變函式

範例

範例 #1 基本的 exit() 範例

<?php

// 正常結束程式
exit();
exit(
0);

// 以錯誤代碼結束
exit(1);

?>

範例 #2 使用 stringexit() 範例

<?php

$filename
= '/path/to/data-file';
$file = fopen($filename, 'r')
or exit(
"unable to open file ($filename)");

?>

範例 #3 關閉函式和解構函式無論如何都會執行

<?php
class Foo
{
public function
__destruct()
{
echo
'Destruct: ' . __METHOD__ . '()' . PHP_EOL;
}
}

function
shutdown()
{
echo
'Shutdown: ' . __FUNCTION__ . '()' . PHP_EOL;
}

$foo = new Foo();
register_shutdown_function('shutdown');

exit();
echo
'This will not be output.';
?>

以上範例會輸出

Shutdown: shutdown()
Destruct: Foo::__destruct()

範例 #4 exit() 作為陳述式

<?php

// 以退出代碼 0 正常結束程式
exit;

?>

注意事項

警告

在 PHP 8.4.0 之前,exit() 是一種語言結構而非函式,因此無法使用可變函式具名引數來呼叫它。

參見

新增註釋

使用者貢獻的註釋 14 則註釋

dexen dot devries at gmail dot com
14 年前
如果您想避免在 FastCGI 中呼叫 exit(),如以下註釋所述,但又真的、確實想要從巢狀函式呼叫或 include 中乾淨地退出,請考慮使用 Python 的方式

定義一個名為 `SystemExit` 的例外,在呼叫 exit() 時拋出它,並在 index.php 中使用一個空的處理程式來攔截它,以乾淨地結束腳本執行。

<?php

// 檔案:index.php
class SystemExit extends Exception {}
try {
/* 程式碼 程式碼 */
}
catch (
SystemExit $e) { /* 什麼都不做 */ }
// 檔案結尾:index.php

// 一些深度巢狀的函式或 .php 檔案

if (SOME_EXIT_CONDITION)
throw new
SystemExit(); // 取代 exit()

?>
albert at removethis dot peschar dot net
15 年前
jbezorg at gmail 建議如下

<?php

if($_SERVER['SCRIPT_FILENAME'] == __FILE__ )
header('Location: /');

?>

在發送 `Location:` 標頭後,PHP _會_ 繼續解析,並且 header() 呼叫下方的所有程式碼仍會被執行。因此,請改用

<?php

if($_SERVER['SCRIPT_FILENAME'] == __FILE__)
{
header('Location: /');
exit;
}

?>
theonenkl at gmail dot com
9 年前
關於 finally 與 exit 搭配使用的一個附註:如果您在 try 區塊中的某處使用 exit,則 finally 將不會被執行。這聽起來可能不那麼明顯:例如,在 Java 中,您永遠不會使用 exit,至少會在控制器中使用 return;而在 PHP 中,您可能會發現自己從控制器方法中退出(例如,在您發出重新導向的情況下)。

以下是概念驗證程式碼 (POC)

<?php
echo "測試 finally 與 exit\n";

try {
echo
"在 try 區塊中,正在退出\n";

exit;
} catch(
Exception $e) {
echo
"已捕捉\n";
} finally {
echo
"在 finally 區塊中\n";
}

echo
"最後\n";
?>

這將會印出

測試 finally 與 exit
在 try 區塊中,正在退出
tianyiw at vip dot qq dot com
2 年前
這些是 Linux 或 UNIX 中的標準錯誤代碼。

1 - 一般錯誤的通用代碼
2 - 誤用 shell 內建指令(根據 Bash 文件)
126 - 無法執行呼叫的指令
127 - 「找不到指令」
128 - 傳遞給 exit 的參數無效
128+n - 致命錯誤訊號「n」
130 - 指令碼被 Control-C 終止
255\* - 退出狀態超出範圍
vincent dot laag at gmail dot com
14 年前
不要在使用 FastCGI 的自動前置檔案中使用 exit() 函式(Linux/BSD 作業系統)。
它會導致檔案保持開啟狀態,至少會產生「開啟的檔案過多…」的錯誤。
chris at ocproducts dot com
6 年前
呼叫 `exit` 會繞過 `auto_append_file` 選項。
在某些免費主機上,這可能會導致您的帳戶被移除,因為他們可能會使用它來放置廣告和分析。

因此,如果在最常用的輸出分支上使用它,請務必小心。
emils at tvnet dot lv
21 年前
請注意,如果 PHP 作為 Roxen SAPI 模組使用,則使用 `exit()` 會明確導致 Roxen 網頁伺服器停止運作。除了不使用 `exit()` 之外,沒有其他已知的解決方法。CGI 版本的 PHP 不受影響。
void a t informance d o t info
16 年前
致 rich dot lovely at klikzltd dot co dot uk

在建構任何正式網站時,在 `header()` 之前使用 "@" 來抑制其錯誤,並依賴「標頭已發送」錯誤訊息,在我看來是一個非常糟糕的主意。

這*不是*防止檔案被直接呼叫的乾淨方法。至少這不是一個安全的方法,因為您依賴於解析器在執行時發送的例外狀況。

我建議使用更常見的方法,例如定義一個常數或賦值給一個變數,並在被引入的腳本中檢查其是否存在,例如:

在 index.php 中
<?php
define
('INDEX', true);
?>

在您引入的檔案中
<?php
if (!defined('INDEX')) {
die(
'您不能直接呼叫這個腳本!');
}
?>

此致。

Ninj
m dot libergolis at gmail dot com
9 年前
除了 "void a t informance d o t info" 的方法之外,這裡還有一種不需要常數的單行寫法:

<?php basename($_SERVER['PHP_SELF']) == basename(__FILE__) && die('你不能通過!'); ?>

將其放在 PHP 檔案的開頭將防止直接存取該腳本。

要重定向到 / 而不是停止執行

<?php
if (basename($_SERVER['PHP_SELF']) == basename(__FILE__)) {
if (
ob_get_contents()) ob_clean(); // ob_get_contents() 即使沒有啟用輸出緩衝也能運作
header('Location: /');
die;
}
?>

用單行寫法實現相同的功能

<?php basename($_SERVER['PHP_SELF']) == basename(__FILE__) && (!ob_get_contents() || ob_clean()) && header('Location: /') && die; ?>

安全性注意事項:即使 $_SERVER['PHP_SELF'] 來自使用者,也可以假設其有效性,因為「操作」發生在實際檔案執行_之前_,這表示該字串_必須_有效才能執行檔案。此外,basename() 是二進位安全的,因此您可以安全地依賴此函式。
jean dot claveau at gmail dot com
4 年前
請注意,如果您啟用了 uopz 擴充功能,它預設會停用 exit / die()。它們只是被「跳過」了。

https://php.dev.org.tw/manual/en/function.uopz-allow-exit.php
alexyam at live dot com
12 年前
使用 php-fpm 時,應該使用 fastcgi_finish_request() 取代 register_shutdown_function() 和 exit()

例如,在 nginx 和 php-fpm 5.3+ 下,這會使瀏覽器等待 10 秒才能顯示輸出

<?php
echo "您必須等待 10 秒才能看到這個訊息。<br>";
register_shutdown_function('shutdown');
exit;
function
shutdown(){
sleep(10);
echo
"因為 exit() 並不會立即終止 php-fpm 呼叫。<br>";
}
?>

而這個不會

<?php
echo "您可以在瀏覽器中立即看到這個訊息。<br>";
fastcgi_finish_request();
sleep(10);
echo
"您在瀏覽器中看不到這個訊息。";
?>
devinemke at devinemke dot com
22 年前
如果您使用包含許多 include 的模板,則 exit() 將會結束您的腳本,並且您的模板將無法完成(沒有 </table>、</body>、</html> 等...)。与其在您的內容中使用複雜的巢狀條件邏輯,不如建立一個「footer.php」檔案來關閉所有 HTML,如果您想退出腳本,只需在 exit() 之前 include() 這個 footer 檔案即可。

例如

include ('header.php');
blah blah blah
if (!$mysql_connect) {
echo "無法連線";
include ('footer.php');
exit;
}
blah blah blah
include ('footer.php');
bill dot gates at hotmail dot com
3 年前
請注意 PHP 的 uopz(User Operations for Zend)擴充功能。預設情況下,啟用此擴充功能後,它會停用(阻止)在呼叫 `exit()` 和 `die()` 時停止 PHP 腳本(FPM 和 CLI)。因此,您的腳本將繼續執行。

詳情:https://php.dev.org.tw/manual/en/uopz.configuration.php#ini.uopz.exit
sunfundev at gmail dot com
7 年前
>> 關閉函式和物件解構函式即使在呼叫 exit 時也將會被執行。

如果您在解構函式中呼叫 exit,這是錯誤的。

正常退出
<?php
類別 A
{
公開函式
__destruct()
{
echo
"bye A\n";
}
}

類別
B
{
公開函式
__destruct()
{
echo
"bye B\n";
}
}

$a = new A;
$b = new B;
exit;

// 輸出:
// bye B
// bye A
?>

// 在解構子中執行 exit
<?php
類別 A
{
公開函式
__destruct()
{
echo
"bye A\n";
}
}

類別
B
{
公開函式
__destruct()
{
echo
"bye B\n";
exit;
}
}

$a = new A;
$b = new B;

// 輸出:
// bye B
?>
To Top