macOS 下搭建 ThinkPHP 3 开发环境(PHP 5.6 + Caddy)

遇到用 ThinkPHP 3 的项目,需要搭建本地开发环境。本文记录这个过程,作为备忘。

环境介绍

我的电脑运行的是 Apple M1 芯片的 macOS 系统。

PHP 选用 5.6,一来项目不完全兼容 PHP 7/8,二来跟生产环境保持一致,不少阿里云的云虚拟主机最高支持 PHP 7.2。

服务器选择了 Caddy,虽然生产环境使用 Apache 或者 Nginx,但在本地开发,我想试一试比较新的 Caddy。

工具安装

PHP 5.6 寿命早已经结束,已经 Homebrew 官方源删除了,因此只能从第三方渠道安装:

1brew tap shivammathur/php
2brew install shivammathur/php/php@5.6

安装 Caddy:

1brew install caddy

服务配置

Apache 有很多种支持 PHP 的方法,除了 Apache 自带模块 mod_php,还有很多 CGI 方案,不容易搞清楚,其中最重要当属 php-fpm 了:

php-fpm 是一个 PHP FastCGI 服务器,我们需要将浏览器发送来请求,根据路径把其中需要 PHP 处理的请求,通过反向代理,通知 php-fpm 处理。

首先,启动 php-fpm。按照 brew info php@5.6 提到的方法。默认监听端口是 9000,由 php-fpm.ini 指定。

1brew services start php@5.6

然后,简单配置 Caddy,路径包含 .php 的请求,会传给 FastCGI 服务器,而静态文件则直接发送文件:

1# Caddyfile
2
3localhost {
4 root * /Users/xcy/work/www
5 php_fastcgi localhost:9000
6 file_server
7}

php_fastcgi 默认把 index.php 当为路由文件(入口文件),这与 ThinkPHP 3 一致,然后我们通过 ThinkPHP 3 所谓的 URL模式之兼容模式 访问网站了:

另外,ThinkPHP 3 所谓的 PATHINFO 模式(也是默认模式),Caddy 也支持,比如:

REWRITE 模式

但是我们的项目配置了 REWRITE 模式:

1// config.php
2 
3'URL_MODEL' => 2, // URL 模式,2 表示 REWRITE 模式

REWRITE 模式比 PATHINFO 模式只少了 index.php,比如:

这个时候需要更新配置 Caddy 了,利用 try_files 把不匹配静态文件的请求,全发送给 index.php 处理:

1# Caddyfile
2
3localhost {
4 root * /Users/xcy/work/www
5 php_fastcgi localhost:9000 {
6 try_files {path} /index.php/{path}
7 }
8 file_server
9}

伪静态

最后一个需求是所谓【伪静态】,把链接简化下,在最后面加上 .html,让动态生成的内容,看上去是一个静态文件,比如:

  • /Home/Article/about 改成 /about.html
  • /Home/News/detail/id/98 改成 /news-98.html

对应的 .htaccess 配置:

1<IfModule mod_rewrite.c>
2 RewriteEngine On
3
4 RewriteRule ^about\.html$ /index.php?s=/Home/Article/about [NC,L]
5
6 RewriteRule ^news-([0-9]+)\.html$ /index.php?s=/Home/News/detail/id/$1.html [NC,L]
7
8 RewriteCond %{REQUEST_FILENAME} !-f
9 RewriteCond %{REQUEST_FILENAME} !-d
10 RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
11</IfModule>

修改我们的 Caddyfile:

1# Caddyfile
2
3localhost {
4 root * /Users/xcy/work/www
5 php_fastcgi localhost:9000 {
6 try_files {path} /index.php/{path}
7 }
8 file_server
9
10 rewrite /about.html /index.php/Home/Article/about
11
12 @news path_regexp news ^/news-([0-9]+).html$
13 rewrite @news /index.php/Home/News/detail/id/{re.news.1}
14}