纤程

Fibers 中调用 PHP 函数和语言结构时,如果它们本身调用了 cgo,已知会导致崩溃。

这个问题正在由 Go 项目进行解决

与此同时,一个解决方案是不要在纤程内部使用委托给 Go 的结构(如 echo)和函数(如 header())。

以下代码可能会因为使用纤程中的 echo 而崩溃:

  1. $fiber = new Fiber(function() {
  2. echo 'In the Fiber'.PHP_EOL;
  3. echo 'Still inside'.PHP_EOL;
  4. });
  5. $fiber->start();

相反,从纤程返回值并在外部使用它:

  1. $fiber = new Fiber(function() {
  2. Fiber::suspend('In the Fiber'.PHP_EOL);
  3. Fiber::suspend('Still inside'.PHP_EOL);
  4. });
  5. echo $fiber->start();
  6. echo $fiber->resume();
  7. $fiber->resume();

不兼容的 PHP 扩展

已知以下扩展与 FrankenPHP 不兼容:

名称 原因 替代品
imap 不是线程安全的 javanile/php-imap2, webklex/php-imap
newrelic 不是线程安全的 -

有缺陷的 PHP 扩展

使用 FrankenPHP 时,以下扩展存在已知的错误和意外行为:

名称 问题
ext-openssl 当使用 FrankenPHP 的静态构建(使用 musl libc 构建)时,OpenSSL 扩展在重负载下可能会崩溃。一个变通办法是使用动态链接的构建(如 Docker 镜像中使用的构建)。这个错误正在由 PHP 跟踪

get_browser

get_browser() 函数似乎在一段时间后表现不佳。一个变通办法是缓存(例如使用 APCu)每个 User Agent 的结果,因为它们是静态的。

独立二进制文件和基于 Alpine 的 Docker 镜像

独立二进制文件和基于 Alpine 的 docker 镜像 (dunglas/frankenphp:*-alpine) 使用 musl libc 而不是 glibc 和 friends,以保持较小的二进制文件大小。这可能会导致一些兼容性问题。特别是,glob 标志 GLOB_BRACE 不可用

在 Docker 中使用 https://127.0.0.1

默认情况下,FrankenPHP 为 localhost 生成一个 TLS 证书。这是本地开发中最简单且推荐的选择。

如果你真的想使用 127.0.0.1 作为主机,可以通过将服务器名称设置为 127.0.0.1 来配置它生成证书。

不幸的是,在使用 Docker 时,由于 其网络系统,这还不够。你会遇到类似的 TLS 错误 curl: (35) LibreSSL/3.3.6: error:1404B438:SSL routines:ST_CONNECT:tlsv1 alert internal error

如果你使用的是 Linux,一个解决方案是使用 宿主网络驱动程序

  1. docker run \
  2. -e SERVER_NAME="127.0.0.1" \
  3. -v $PWD:/app/public \
  4. --network host \
  5. dunglas/frankenphp

宿主网络驱动程序在 Mac 和 Windows 上不受支持。在这些平台上,你需要猜测容器的 IP 地址并将其包含在服务器名称中。

运行 docker network inspect bridge 并查看 Containers 键,以根据 IPv4Address 键下当前分配的最后一个 IP 地址,并将其加一。如果没有容器正在运行,通常分配的第一个 IP 地址是 172.17.0.2

然后,将此包含在 SERVER_NAME 环境变量中:

  1. docker run \
  2. -e SERVER_NAME="127.0.0.1, 172.17.0.3" \
  3. -v $PWD:/app/public \
  4. -p 80:80 -p 443:443 -p 443:443/udp \
  5. dunglas/frankenphp

注意

确保将 172.17.0.3 替换为你的容器将被分配的 IP。

现在你应该能够从宿主机访问 https://127.0.0.1

如果不是这样,请在调试模式下启动 FrankenPHP 以尝试找出问题:

  1. docker run \
  2. -e CADDY_GLOBAL_OPTIONS="debug" \
  3. -e SERVER_NAME="127.0.0.1" \
  4. -v $PWD:/app/public \
  5. -p 80:80 -p 443:443 -p 443:443/udp \
  6. dunglas/frankenphp

引用 @php 的 Composer 脚本

Composer 脚本 可能希望为某些任务执行 PHP 二进制文件,例如在 Laravel 项目 中运行 @php artisan package:discover --ansi。这目前因为两个原因失败

  • Composer 不知道如何调用 FrankenPHP 二进制文件;
  • Composer 可能会在命令中使用 -d 标志添加 PHP 设置,而 FrankenPHP 尚未支持。

作为一种变通办法,我们可以在 /usr/local/bin/php 中创建一个 shell 脚本,该脚本剥离不支持的参数,然后调用 FrankenPHP:

  1. #!/usr/bin/env bash
  2. args=("$@")
  3. index=0
  4. for i in "$@"
  5. do
  6. if [ "$i" == "-d" ]; then
  7. unset 'args[$index]'
  8. unset 'args[$index+1]'
  9. fi
  10. index=$((index+1))
  11. done
  12. /usr/local/bin/frankenphp php-cli ${args[@]}

然后将环境变量 PHP_BINARY 设置为我们的 php 脚本路径,composer 应该可以通过:

  1. export PHP_BINARY=/usr/local/bin/php
  2. composer install