PHP Conference Japan 2024

exit

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

exit使用状态码或消息终止当前脚本

描述

exit(字符串|整数 $status = 0): never

终止脚本的执行。即使调用了exit(),也会始终执行关闭函数对象析构函数。但是,finally块永远不会执行。

退出代码0用于指示程序已成功完成其任务。任何其他值都表示在执行过程中发生了一些错误。

exit()是一个特殊的函数,因为它在解析器中有一个专用的标记,因此它可以像语句一样(即不带括号)用于以默认状态码终止脚本。

注意

无法禁用或创建命名空间函数来隐藏全局exit()函数。

参数

status
如果status是字符串,则此函数在退出之前打印status。PHP 返回的退出代码为0

如果status整数,则PHP 返回的退出代码将为status

注意: 退出代码应在0254的范围内,退出代码255由PHP保留,不应使用。

警告

在 PHP 8.4.0 之前,exit() 并没有遵循 PHP 标准的类型转换语义,也不尊重strict_types声明。

任何不是整数类型的值都会被转换为字符串,包括资源数组值。从 PHP 8.4.0 开始,它遵循通常的类型转换语义,并在无效值上抛出TypeError异常。

返回值

由于这会终止 PHP 脚本,因此不会返回任何值。

变更日志

版本 描述
8.4.0 exit()现在是一个真正的函数,因此它遵循通常的类型转换语义,受strict_types声明的影响,可以用具名参数调用,并且可以作为变量函数

示例

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

<?php

// 正常退出程序
exit();
exit(
0);

// 使用错误代码退出
exit(1);

?>

示例 #2 exit() 使用字符串的示例

<?php

$filename
= '/path/to/data-file';
$file = fopen($filename, 'r')
or exit(
"无法打开文件 ($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
'这不会输出。';
?>

上面的示例将输出

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(),如以下评论所示,但确实希望从嵌套函数调用或包含中干净地退出,请考虑使用 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 _将_ 继续解析,并且头部() 调用下面的所有代码仍将执行。因此,请改用

<?php

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

?>
theonenkl at gmail dot com
9年前
关于在 finally 中使用 exit 的一个旁注:如果在 try 块中的某个地方退出,则不会执行 finally。这可能并不明显:例如,在 Java 中,你永远不会发出 exit,至少在你的控制器中返回;而在 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(linux/bsd 操作系统)的自动前置文件中使用 exit() 函数。
它会导致打开的文件保持打开状态,至少会导致一个友好的“打开文件过多...”错误。
chris at ocproducts dot com
6年前
调用 'exit' 将绕过 auto_append_file 选项。
在一些免费主机上,这可能会导致你被移除,因为他们可能正在使用它进行广告和分析。

因此,如果在最常见的输出分支上使用它,请谨慎。
emils at tvnet dot lv
21年前
请注意,如果 PHP 用作 Roxen SAPI 模块,则使用 exit() 将显式导致 Roxen Web 服务器终止。除了不使用 exit() 之外,没有已知的解决方法。PHP 的 CGI 版本不受影响。
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.net/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年前
如果您使用包含大量包含文件的模板,则 exit() 将结束您的脚本,并且您的模板将无法完成(没有</table>、</body>、</html> 等)。与其在内容中使用复杂的嵌套条件逻辑,不如创建一个“footer.php”文件,用于关闭所有 HTML,如果要退出脚本,只需在退出之前包含() 页脚即可。

例如

include ('header.php');
等等等等
if (!$mysql_connect) {
echo "无法连接";
include ('footer.php');
exit;
}
等等等等
include ('footer.php');
bill dot gates at hotmail dot com
3年前
请注意 PHP 的 uopz(Zend 的用户操作)扩展。它默认在启用扩展后立即禁用(阻止)在调用 `exit()` 和 `die()` 时停止 PHP 脚本(FPM 和 CLI)。因此,您的脚本将继续执行。

详情:https://php.net/manual/en/uopz.configuration.php#ini.uopz.exit
sunfundev at gmail dot com
7年前
>> 即使调用 exit,关闭函数和对象析构函数也将始终执行。

如果在析构函数中调用 exit,则为假。

正常退出
<?php
A
{
public function
__destruct()
{
echo
"bye A\n";
}
}

B
{
public function
__destruct()
{
echo
"bye B\n";
}
}

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

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

// 退出到析构函数
<?php
A
{
public function
__destruct()
{
echo
"bye A\n";
}
}

B
{
public function
__destruct()
{
echo
"bye B\n";
exit;
}
}

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

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