问题描述
例如这段代码
<?PHP
if (some_condition()) {
header('Location: /');
exit();
}
// do a lot of things...
在经典的 PHP FPM 上,以前的代码工作正常。但是在 PHP+Swoole 上,我们得到这个错误
swoole exit {"exception":"[object] (Swoole\\ExitException(code: 0): swoole exit at
解决方法
对于 PHP FPM,每段代码都是单独执行的,结果(该过程的输出)通过管道返回给客户端。因此,每当我们想停止处理时,我们只需触发 exit()
。
然而,使用 Swoole,服务器应该一直运行。当然,可以使用 Swoole\Process::exit() stop the Process - 但通常由控制器来触发立即发送响应。例如:
$server = new Swoole\HTTP\Server("127.0.0.1",9501);
$server->on("start",function (Swoole\Http\Server $server) {
echo "Swoole http server is started at http://127.0.0.1:9501\n";
});
$server->on("request",function (Swoole\Http\Request $request,Swoole\Http\Response $response) {
$response->header("Content-Type","text/plain");
$response->end("Hello World\n");
});
$server->start();
在这种情况下,$response->end
是与 PHP FPM 世界中的 exit()
基本相同的方法。请注意,它与 Node 世界中发生的情况非常相似:服务器应该一直运行,并且由控制器(处理每个单独请求的函数)决定是否停止处理单个请求并传回响应,包括标头和身体。
如何在 Laravel + Swoole 上替换 exit()
是的,exit()
函数是一种非常糟糕的做法。但是自己的 Laravel 应用程序会引导一个旧代码。那么,根据相关成本,这种方式是更好的解决方案。
- 做一个可渲染的异常
class ExitException extends Exception implements Renderable
{
public function report() {
return true; // dont report
}
public function render()
{
return ' '; // prevent 500 html dump error
}
}
- 将
exit();
替换为
// exit;
throw new ExitException();
该异常将由您的应用程序错误处理程序处理,并向 Swoole 请求处理程序发送一个空字符串作为响应。
我再说一遍:这不是一个优雅的解决方案,只是防止更改旧应用程序上的大量代码。
,您可以了解\Swoole\ExitException
。
use Swoole\Coroutine;
use function Swoole\Coroutine\run;
function route()
{
controller();
}
function controller()
{
your_code();
}
function your_code()
{
Coroutine::sleep(.001);
exit(1);
}
run(function () {
try {
route();
} catch (\Swoole\ExitException $e) {
var_dump($e->getMessage());
var_dump($e->getStatus() === 1);
var_dump($e->getFlags() === SWOOLE_EXIT_IN_COROUTINE);
}
});