PHP 多版本环境管理指南(phpenv 教程)
谁懂这种痛苦?
在 OrbStack 的 Ubuntu 虚拟机里开发 PHP 项目,经常需要同时维护几个不同版本的项目:
- 项目A还停留在7.4
- 项目B刚升级到8.1
- 新项目已经跑在8.3
以前的做法要么在 Ubuntu 里装一堆版本,用php7.4、php8.1这样的命令手动指定,要么用 update-alternatives 切全局版本。时间长了很容易敲错,尤其是那些半年不碰一次的边缘项目,突然要进行修改完全想不起当时用的是哪个版本,还得去翻历史记录或服务器配置。
后来我把 phpenv 整起来了,现在进项目目录自动切换版本,用起来顺手多了。下面把整个配置过程记录一下,基本都是一次性搞定,后续装新版本几乎不用再动。
1.安装 phpenv 和 php-build
先把工具和 php-build 插件拉下来,我这里命令行用到是 zsh,顺便把环境变量设置上。
Bash
# 克隆 phpenv
git clone https://github.com/phpenv/phpenv.git ~/.phpenv
echo 'export PATH="$HOME/.phpenv/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(phpenv init -)"' >> ~/.zshrc
source ~/.zshrc
# 安装 php-build 插件,php 多版本编译主要靠这个插件
git clone https://github.com/php-build/php-build $(phpenv root)/plugins/php-build
2. 设置默认编译选项
php-build 默认的编译参数比较保守,我直接改成一套常用的扩展全开,顺带把 PEAR 也装上,后面用 pecl 就方便了。这个配置也可以根据自己的需求自行调整
# 找到配置文件
cd ~/.phpenv/plugins/php-build/share/php-build
vim default_configure_options
# 直接把下面这段贴进去,覆盖原来的
# 在 PHP 8+ 中,--with-pear 可能不再自动安装 PEAR/PECL,需要手动安装
--with-pear
--enable-sockets
--enable-exif
--with-zlib
--with-zlib-dir=/usr
--with-bz2
--enable-intl
--with-openssl
--enable-soap
--enable-xmlreader
--with-xsl
--enable-ftp
--enable-cgi
--with-curl=/usr
--with-tidy
--with-xmlrpc
--enable-sysvsem
--enable-sysvshm
--enable-shmop
--with-mysqli=mysqlnd
--with-pdo-mysql=mysqlnd
--with-pdo-sqlite
--enable-pcntl
--with-readline
--enable-mbstring
--disable-debug
--enable-fpm
--enable-bcmath
--enable-phpdbg
3. pecl 自动生成 ini 文件
默认情况下用 pecl install 装扩展后需要手动建 ini 文件,容易忘。装这个插件可以自动处理。
在 PHP 8+ 中,–with-pear 可能不再自动安装 PEAR/PECL,需要手动安装。
# 安装插件
git clone https://github.com/sergeyklay/phpenv-pear-setup.git ~/.phpenv/plugins/phpenv-pear-setup
# 每次新增 php 版本后跑一下这个
phpenv pear-setup
phpenv rehash
4. 安装编译依赖
如果是新启动的 Ubuntu php 版本编译时使用到的依赖是缺失的,如果这时候直接去安装 php 版本会报错,提示依赖库不存在,这个是需要使用到依赖,可以提前安装一下或者碰到缺少哪个依赖再去安装哪个依赖库也行
sudo apt update
sudo apt install -y
autoconf automake libtool bison re2c pkg-config build-essential
bzip2 libbz2-dev
libxml2-dev libxslt1-dev
libssl-dev libcurl4-openssl-dev
libpng-dev libjpeg-turbo8-dev
libicu-dev
libreadline-dev
libsqlite3-dev
libonig-dev
libzip-dev
libtidy-dev
5. 自动配置 PHP-FPM(不使用 FPM 可以忽略)
phpenv 只管 PHP 二进制,不处理 FPM 的启动和 socket。我写了个 after-install 脚本,装完版本后自动:
- 创建 socket 目录
- 修改 www.conf 使用 unix socket
- 生成并启用systemd user服务
创建目录:mkdir -p ~/.phpenv/plugins/php-build/share/php-build/after-install.d
创建脚本:vim ~/.phpenv/plugins/php-build/share/php-build/after-install.d/setup-fpm
#!/usr/bin/env bash
set -e
# 动态获取 PHP 路径和版本
PHP_PREFIX="$PREFIX"
VERSION="$(basename "$PHP_PREFIX")"
USER_NAME=$(whoami)
# 定义路径
SOCKET_DIR="$PHP_PREFIX/var/run"
SOCKET_PATH="$SOCKET_DIR/php$VERSION.sock"
SYSTEMD_DIR="$HOME/.config/systemd/user"
SERVICE_NAME="phpenv-${VERSION}-fpm.service"
SERVICE_PATH="$SYSTEMD_DIR/$SERVICE_NAME"
echo "=== 正在自动配置 PHP-FPM $VERSION ==="
# 创建目录
mkdir -p "$SOCKET_DIR"
mkdir -p "$SYSTEMD_DIR"
# 修改 FPM 配置,改用 Unix Socket 并修正权限
POOL_CONF="$PHP_PREFIX/etc/php-fpm.d/www.conf"
if [ -f "$POOL_CONF" ]; then
sed -i "s|^listen = .*|listen = $SOCKET_PATH|" "$POOL_CONF"
sed -i "s|;listen.owner = .*|listen.owner = $USER_NAME|" "$POOL_CONF"
sed -i "s|;listen.group = .*|listen.group = $USER_NAME|" "$POOL_CONF"
sed -i "s|;listen.mode = .*|listen.mode = 0666|" "$POOL_CONF"
fi
# 写入 Systemd User Service
cat > "$SERVICE_PATH" <<EOF
[Unit]
Description=PHP-FPM $VERSION (phpenv)
After=network.target
[Service]
ExecStart=$PHP_PREFIX/sbin/php-fpm -F -y $PHP_PREFIX/etc/php-fpm.conf
Restart=always
[Install]
WantedBy=default.target
EOF
# 注册并启动
systemctl --user daemon-reload
systemctl --user enable "$SERVICE_NAME"
systemctl --user restart "$SERVICE_NAME"
echo "=== PHP-FPM $VERSION 启动成功 ==="
echo "Socket: $SOCKET_PATH"
记得给执行权限: chmod +x ~/.phpenv/plugins/php-build/share/php-build/after-install.d/setup-fpm
6. 使用方式
现在你想装一个 PHP 8.2.29,只需要: phpenv install 8.2.29
安装过程会自动触发脚本,完成FPM配置并启动服务。在Nginx里直接配置:
fastcgi_pass unix:/home/youruser/.phpenv/versions/8.2.29/var/run/php8.2.29.sock;
项目里切换版本,到项目目录下,执行下面这个命令就可以,之后在这个项目目录下执行 php 命令自动指向这个 8.2.29 版本了。
# 设置当前目录 php 版本,会生成一个 .phpenv 文件
phpenv local 8.2.29
# 验证设置是否成功,会输出当前目录下使用的 php 版本
phpenv version
本作品采用《CC 协议》,转载必须注明作者和本文链接
关于 LearnKu
补充一个 PHP8+ 版本自动安装 PECL 脚本
在这个目录下创建脚本即可
~/.phpenv/plugins/php-build/share/php-build/after-install.d感谢分享, 一直在用 update-alternatives, 还在想哪天换一个类似rbenv之类的. 这个很全, 太赞了!