Featured image of post PHP 7.4 实战:Nginx + PHP-CGI + Xdebug 调试一体化

PHP 7.4 实战:Nginx + PHP-CGI + Xdebug 调试一体化

Windows 下搭建 PHP 7.4 运行环境:Nginx 反代、PHP-CGI 启动、Xdebug 远程调试、常见错误速查

前置知识

  • Windows 命令行基础(cmd / PowerShell)
  • 知道什么是 Web 服务器、什么是 CGI
  • 至少跑过一个 PHP 页面

为什么 2020 年还在用 PHP

2010 年代后期,Go / Node.js / Python Web 框架方兴未艾,唱衰 PHP 的声音不断——“性能差”、“语法老”、“现代特性缺”。但 PHP 7.4(2019-11 发布)做了一次关键升级:

  • PHP 7.0 vs 5.6 性能提升 2 倍(WordPress 主页 QPS 从 100 涨到 300+)
  • OPcache 集成(字节码缓存默认开启)
  • 类型属性(class 属性可以声明 intstring
  • 箭头函数fn($x) => $x * 2
  • 预加载(PHP 7.4 新特性,把框架文件预加载到 OPCache)

WordPress 占据全球 40%+ 的网站、Magento / Laravel 长期稳居主流——PHP 工程师的需求量在 2020 年依然巨大。学 PHP 7.4 是性价比最高的后端入门选择

一、Windows 下 PHP 7.4 + Nginx 一体化搭建

1.1 下载三件套

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 1. Nginx 1.18
# 官网下载 stable 版
# https://nginx.org/en/download.html

# 2. PHP 7.4.6 (NTS, x64, VC15)
# https://windows.php.net/download/
# 选 php-7.4.6-nts-Win32-vc15-x64.zip

# 3. RunHiddenConsole.exe
# 一个 1KB 工具,让 nginx / php 以后台方式跑
# 网上搜 RunHiddenConsole 下载

1.2 目录规划

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<PHP_SOFT_DIR>
├── nginx-1.18.0\
├── php-7.4.6\
│   ├── php.exe
│   ├── php.ini
│   ├── ext\
│   └── php-cgi.exe
├── RunHiddenConsole.exe
├── start.bat    # 一键启动
└── stop.bat     # 一键停止

1.3 PHP 7.4 配置(php.ini)

php.ini-development 复制一份改名为 php.ini

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
; 时区(中国)
date.timezone = Asia/Shanghai

; 扩展目录
extension_dir = "ext"

; 启用常用扩展
extension=curl
extension=fileinfo
extension=gd2
extension=mbstring
extension=mysqli
extension=openssl
extension=pdo_mysql
extension=xml
extension=zip

; CGI 相关
enable_dl = On
cgi.force_redirect = 0
fastcgi.impersonate = 1
cgi.rfc2616_headers = 1

; 上传文件大小
upload_max_filesize = 50M
post_max_size = 50M
memory_limit = 256M

1.4 Nginx 配置

编辑 nginx-1.18.0\conf\nginx.conf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
worker_processes  1;
events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    charset utf-8;  # 第 39 行去 # 改 utf-8

    server {
        listen       80;
        server_name  localhost;

        # 站点根目录
        root   D:/workspace/soft/nginx/www;
        index  index.php index.html;

        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }

        # PHP 处理
        location ~ \.php$ {
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }
    }
}

1.5 启动脚本

start.bat(双击启动):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@echo off
cd /d <PHP_SOFT_DIR>

REM 启动 PHP-CGI(监听 9000 端口)
start /b "php-cgi" "RunHiddenConsole.exe" "php-7.4.6\php-cgi.exe" -b 127.0.0.1:9000 -c "php-7.4.6\php.ini"

REM 启动 Nginx
start /b "nginx" "RunHiddenConsole.exe" "nginx-1.18.0\nginx.exe"

echo PHP-CGI and Nginx started in background.
pause

stop.bat

1
2
3
4
5
@echo off
taskkill /F /IM nginx.exe
taskkill /F /IM php-cgi.exe
echo Stopped.
pause

1.6 验证

1
2
3
4
5
6
# 检查进程
tasklist | findstr "nginx"
tasklist | findstr "php-cgi"

# 浏览器访问
# http://localhost

新建 <PHP_SOFT_DIR>nginx\www\index.php

1
2
<?php
    phpinfo();

看到 PHP 7.4.6 配置页 = 成功。

二、Xdebug 远程调试

Xdebug 是 PHP 调试的事实标准——和 Java 的 JDWP、Python 的 pdb 一样,可以在 IDE 里打断点、单步执行、查看变量。

2.1 下载 Xdebug

打开 https://xdebug.org/download,选对应 PHP 版本的 dll:

  • PHP 7.4 NTS x64php_xdebug-2.9.5-7.4-vc15-nts-x86_64.dll
  • PHP 7.4 TS x64php_xdebug-2.9.5-7.4-vc15-ts-x86_64.dll

⚠️ NTS / TS 一定要对(NTS = Non-Thread-Safe,TS = Thread-Safe)——错版本直接起不来。

放到 php-7.4.6\ext\ 目录下。

2.2 php.ini 启用 Xdebug

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[xdebug]
zend_extension = <PHP_SOFT_DIR>php-7.4.6\ext\php_xdebug-2.9.5-7.4-vc15-nts-x86_64.dll

; 远程调试配置
xdebug.idekey = PHPXDEBUG
xdebug.remote_enable = 1
xdebug.remote_host = 127.0.0.1
xdebug.remote_port = 9001
xdebug.remote_handler = dbgp
xdebug.remote_autostart = 1

2.3 IDEA / PhpStorm 配置

Settings → PHP

字段
PHP language level7.4
CLI Interpreter<PHP_SOFT_DIR>php-7.4.6\php.exe

Settings → PHP → Debug

  • Xdebug
  • Debug port: 9001

Settings → PHP → Debug → DBGp Proxy

  • IDE key: PHPXDEBUG
  • Host: 127.0.0.1
  • Port: 9000

Settings → PHP → Servers

  • Name: php7.4 Server
  • Host: 127.0.0.1
  • Port: 80
  • Debugger: Xdebug

PHP → Debug → Start Listening(点电话图标变绿 = 监听中)。

2.4 Chrome / Postman 触发断点

方法 1:Chrome 装 Xdebug helper 插件

  • 打开插件设置 → IDE key 选 PHPXDEBUG
  • 访问 http://localhost/index.php → IDE 自动中断

方法 2:Postman 加 Cookie

1
Cookie: XDEBUG_SESSION=PHPXDEBUG

或加 query string:

1
GET /index.php?XDEBUG_SESSION_START=PHPXDEBUG

2.5 Xdebug 高级功能

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
; 性能分析(生成 cachegrind 文件,可用 KCacheGrind 看)
xdebug.profiler_enable = 0
xdebug.profiler_enable_trigger = 1
xdebug.profiler_output_dir = "D:\workspace\profiler"

; 代码覆盖率
xdebug.coverage_enable = 1

; 远程 trace(每行函数调用日志)
xdebug.remote_mode = jit
xdebug.trace_output_dir = "D:\workspace\trace"

三、常见错误速查

3.1 Call to undefined function curl_init()

1
2
3
4
; 在 php.ini 加
extension=curl

; 重启 php-cgi

Windows 下还要确认 php-7.4.6\ext\php_curl.dll 存在、<PHP_SOFT_DIR>php-7.4.6 目录里有 libeay32.dll ssleay32.dll(PHP 7.4 自带)。

3.2 SQLSTATE[HY000] [2002] No connection could be made

PDO / mysqli 连不上 MySQL。检查项:

  1. MySQL 服务在跑(net start mysql
  2. localhost vs 127.0.0.1 —— MySQL 用 socket、127.0.0.1 用 TCP,新版 MySQL 默认走 socket,PDO 报 2002
  3. 端口(默认 3306)防火墙是否放行
1
$pdo = new PDO('mysql:host=127.0.0.1;port=3306;dbname=test', 'root', 'password');

3.3 No input file specified.

Nginx 配置的 root 路径和 PHP 文件实际路径不一致。

1
2
3
4
5
6
7
location ~ \.php$ {
    root           D:/workspace/soft/nginx/www;  # ← 必须用 / 不要用 \
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  D:/workspace/soft/nginx/www$fastcgi_script_name;
    include        fastcgi_params;
}

$document_rootfastcgi_param SCRIPT_FILENAME 路径要完全一致。

3.4 500 Internal Server Error

打开 php.ini 错误显示:

1
2
3
4
5
display_errors = On
display_startup_errors = On
error_reporting = E_ALL
log_errors = On
error_log = <PHP_SOFT_DIR>php-7.4.6\logs\php_error.log

重启 php-cgi,看浏览器错误 + log 文件。

3.5 502 Bad Gateway

Nginx 收不到 PHP-CGI 的响应——PHP-CGI 没启动或挂了:

1
2
3
tasklist | findstr php-cgi
# 没结果 → 重启 start.bat
# 有结果但 502 → 检查 php-cgi -b 参数端口是不是 9000

四、生产环境建议

本地调试用 php-cgi.exe + Nginx 够用,但生产绝不能用这套——php-cgi 是单进程、崩溃不会自启、并发上不去。

4.1 用 PHP-FPM 替代

Linux 上一律用 PHP-FPM(FastCGI Process Manager):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Ubuntu
apt install php7.4-fpm
systemctl start php7.4-fpm

# nginx 配置
location ~ \.php$ {
    fastcgi_pass   unix:/var/run/php/php7.4-fpm.sock;  # 走 Unix Socket 比 TCP 快
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;
}

4.2 用 Docker 跑 PHP

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# docker-compose.yml
version: '3'
services:
  php:
    image: php:7.4-fpm-alpine
    volumes:
      - ./www:/var/www/html
    networks:
      - backend

  nginx:
    image: nginx:1.18-alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
      - ./www:/var/www/html
    depends_on:
      - php
    networks:
      - backend

networks:
  backend:

4.3 性能调优清单

默认建议
opcache.enable1保持开启
opcache.memory_consumption128256
opcache.max_accelerated_files1000020000
pm.max_children (FPM)5nproc × 2
pm.start_servers2nproc × 1
request_terminate_timeout030s(防止慢请求占资源)

五、2024 视角:PHP 8.3 升级与 EOL 提醒

⚠️ 重要时间线PHP 7.4 已于 2022-11-28 正式 EOL(End Of Life),不再收到任何安全更新。本文 2020 年写于 7.4 时代,今天(2024+)继续使用 7.4 = 裸奔。强烈建议升级到 PHP 8.3(2023-11 发布,当前 active branch)。

5.1 PHP 7.4 → 8.x 升级成本

好消息:8.0/8.1/8.2/8.3 都是渐进式升级,几乎没有 breaking change:

版本发布EOL升级成本
7.42019-112022-11(已 EOL)
8.02020-112023-11低(Named Args、Match、Attributes)
8.12021-122025-12中(Enums、Fibers、Readonly Properties)
8.22022-122026-12低(DNF Types、Constants in Traits)
8.32023-112027-12低(Typed Class Constants、#[\Override]

5.2 PHP 8.x 关键新特性(精选 6 个)

1. 命名参数(Named Arguments)—— 8.0

1
2
3
4
5
// 之前:靠顺序
htmlspecialchars($str, ENT_QUOTES | ENT_HTML5, 'UTF-8', false);

// 现在:跳着填
htmlspecialchars($str, double_encode: false);

2. Match 表达式 —— 8.0

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// 之前
switch ($status) {
    case 200: $msg = 'OK'; break;
    case 404: $msg = 'Not Found'; break;
    default: $msg = 'Unknown';
}

// 现在
$msg = match (true) {
    $status >= 200 && $status < 300 => 'OK',
    $status === 404 => 'Not Found',
    default => 'Unknown',
};

3. 枚举(Enums) —— 8.1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
enum Status: string
{
    case Active = 'active';
    case Banned = 'banned';
    case Pending = 'pending';

    public function label(): string
    {
        return match ($this) {
            self::Active => '活跃',
            self::Banned => '封禁',
            self::Pending => '待审',
        };
    }
}

4. 只读属性(Readonly Properties) —— 8.1

1
2
3
4
5
6
7
class Money
{
    public function __construct(
        public readonly int $amount,
        public readonly string $currency,
    ) {}
}

5. 纤程(Fibers) —— 8.1(类似 Go goroutine 的简化版)

1
2
3
4
5
6
7
$fiber = new Fiber(function (): void {
    $value = Fiber::suspend('fiber suspended');
    echo "Resumed with: $value\n";
});

$value = $fiber->start();   // "fiber suspended"
$fiber->resume('test');     // "Resumed with: test"

实战意义:让 PHP 能写真正的协程,AmPHP 3 / Revolt / ReactPHP 都基于 Fibers 重写了事件循环。

6. 类型化类常量(Typed Class Constants) —— 8.3

1
2
3
4
5
class HttpStatus
{
    public const int OK = 200;          // 8.3 前是 mixed
    public const string NOT_FOUND = '404 is wrong here';  // 编译期就会报错
}

5.3 PHP 8.x 性能

指标7.48.08.3
WordPress 主页 QPS300350420+
Symfony Welcome 页 QPS1.2k1.5k1.9k
内存峰值(典型 Web 请求)12 MB11 MB9 MB
JIT 编译器tracing JIT(可选)function JIT(默认更智能)

8.3 的 JIT纯计算密集型任务(图像处理、数值计算、规则引擎)能再涨 1.5~3 倍

5.4 7.4 → 8.3 升级路径(最短 4 步)

  1. PHPCompatibility 静态扫描:composer require --dev phpcompatibility/phpcompatibility
  2. 修 deprecation{ 改为 {$var}each()foreach
  3. CI 跑通:把 7.4 跑过的测试在 8.3 跑一遍
  4. 生产灰度:金丝雀 5% → 25% → 50% → 100%

参考工具PHPStan 静态分析、Psalm、Rector(自动重构 7.4 → 8.x 代码)。

5.5 如果还在用 PHP 5.x / 7.0/7.1/7.2/7.3

危险——这些版本都 EOL:

版本EOL 时间风险
5.62019-01已知多个未修复漏洞
7.02019-01同上
7.12019-12同上
7.22020-11同上
7.32021-12同上
7.42022-11最新 EOL,建议立即升级
8.02023-11需升级到 8.1+
8.32027-12当前推荐版本

结论:2024+ 新项目直接用 PHP 8.3;老项目至少升级到 8.1+(还有 1 年多支持),最迟 2025 年前完成 8.2/8.3 升级。


六、下一步

  • PHP 8.3 现代特性(命名参数、Enums、Fibers、Readonly):PHP 8 迁移指南
  • 框架:Laravel 11 / Symfony 7 / ThinkPHP 8——Laravel 仍是事实标准
  • Composer:PHP 包管理——composer require vendor/package
  • 测试:PHPUnit 11 + Mockery + Pest(PHPUnit 之上的现代语法糖)
  • 静态分析:PHPStan / Psalm(类似 TypeScript 的 tsc)
  • 协程:基于 Fibers 的 AmPHP 3 / Revolt

参考资料

使用 Hugo 构建
主题 StackJimmy 设计