☰
怎么在本地多个PHP版本切换来安装Laravel
2026/10/3 4:27:46 网站建设 项目流程

前言

本地装了多个 PHP 版本(比如 PhpStudy 里同时有 7.4、8.0、8.2、8.4),想用其中一个来装 Laravel,结果反复撞上两种怪事:一是在面板里把站点 PHP 切到了 8.2,可composer create-project依然报Your requirements could not be resolved,说需要php >=8.2;二是反过来,命令行装得好好的,浏览器一打开就是 500。

根因只有一个,但很多人一开始没意识到:Web 用的 PHP 和命令行用的 PHP 是两套完全独立的东西。Web 那套由 Web 服务器的处理器决定(Apache 的模块、Nginx 转发到的 FastCGI 端口、IIS 的处理程序映射);命令行那套由PATH环境变量里第一个被找到的php决定。Composer 是命令行程序,它只认后者。面板里点"切换 PHP 版本",改的是前者。

本文把这两条链路分开讲,给出不依赖PATH的调用方式、config.platform的正确用法,以及一套切换后必须做的验证动作。

一、先把两条链路认清楚

维度Web 侧 PHPCLI 侧 PHP
谁决定用哪个版本Apache 的LoadModule/ Nginx 的fastcgi_pass端口 / IIS 的处理器映射PATH里第一个php(php.exe)
由谁配置面板的站点设置、Web 服务器配置文件系统环境变量、终端会话
改完要不要重启要(重启 Web 服务)不要(但已开着的终端要重开)
Composer 用哪个不用用这个
php artisan用哪个不用用这个
验证命令浏览器访问phpinfo()或探测脚本php -v

把这张表记住,绝大多数"切了没用"的困惑当场就消解了。

先分别验证两边到底是什么版本:

# CLI 侧 php -v php --ini # Windows:列出 PATH 里能找到的所有 php where php # Linux / macOS:列出全部 which -a php

Linux 下如果装了多个版本,用 alternatives 机制切换默认的 CLI 版本:

# Debian / Ubuntu sudo update-alternatives --config php # RHEL 系先看模块流里有哪几个版本 dnf module list php

二、Laravel 各版本的 PHP 门槛

这张表决定了"我该切到哪个版本",先看它再动手。

Laravel 版本最低 PHP说明
9.x8.0.2仍在维护周期内的旧项目
10.x8.1大量存量项目在这个版本
11.x8.2要求 PHP 8.2 起
12.x8.2与 11.x 的门槛相同

Composer 在解析依赖时会读composer.json里require.php的约束,例如"php": "^8.2"。^8.2的含义是"大于等于 8.2 且小于 9.0",所以 PHP 8.4 也能满足;但如果某个包写的是~8.2.0,就只接受 8.2.x,8.4 会被拒。

查看依赖对 PHP 的真实要求,不用猜:

# 看 laravel/framework 的所有可用版本及各自的 require 约束 composer show laravel/framework --all # 在当前环境上逐条验证平台要求是否满足 composer check-platform-reqs

三、不依赖 PATH:指定解释器跑 Composer

最稳的做法是永远不要依赖PATH里那个"碰巧是第一个"的 php,而是显式指定解释器。Windows 上写绝对路径即可:

# 用 PHP 8.2 创建 Laravel 12 项目 D:/phpstudy_pro/Extensions/php/php8.2.9nts/php.exe \ D:/phpstudy_pro/Extensions/composer/composer.phar \ create-project laravel/laravel blog "^12.0" # 进入项目后,同样显式指定解释器安装依赖 cd /d D:/phpstudy_pro/WWW/blog D:/phpstudy_pro/Extensions/php/php8.2.9nts/php.exe \ D:/phpstudy_pro/Extensions/composer/composer.phar install

每次都敲一长串路径太痛苦。在项目根目录放一个 Windows 批处理包装脚本(存成php82.bat),把它拖进PATH,或者直接放在项目里用相对路径调用:

@echo off rem php82.bat —— 用固定版本的 PHP 执行传入的命令 set "PHP82=D:\phpstudy_pro\Extensions\php\php8.2.9nts\php.exe" "%PHP82%" %*

有了这个包装脚本,composer的调用就变成:

php82.bat D:\phpstudy_pro\Extensions\composer\composer.phar install php82.bat artisan migrate php82.bat -v

把php82.bat里的路径改成 8.4 的目录,另存成php84.bat,就得到了一个项目级的"版本切换开关",不受系统PATH变化影响。

Linux / macOS 上用 alias 或者一个同名 shell 函数:

# 写进 ~/.bashrc php82() { /usr/bin/php8.2 "$@" }

四、config.platform:让依赖解析按目标版本走

有时候你会遇到一种矛盾:开发机上是 PHP 8.4,但生产服务器只有 PHP 8.2。如果不做任何配置,在 8.4 上composer update解析出来的依赖版本,可能包含了要求php >=8.3的包,拿到生产上就装不起来。

解决办法是在composer.json里声明"我在模拟哪个平台":

composer config platform.php 8.2.9

它会在composer.json里写入:

"config": { "platform": { "php": "8.2.9" } }

从此以后,无论本地实际是 8.4 还是 8.2,Composer 在解析依赖时都当作 8.2.9 来处理。这是正确对齐环境差异的方式,而不是用下面这个:

# 不要这样做:它只是跳过检查,装出来的依赖可能在生产上根本跑不起来 composer install --ignore-platform-reqs

--ignore-platform-reqs会让你在 PHP 8.0 上装出需要 8.2 的包,然后在运行时以"语法错误"或"未定义类"的形式爆炸。它的合理用途只有一个:临时在 CI 里装依赖做静态检查。

五、装完之后必须做的验证

切换 PHP 版本后,别急着打开浏览器。按顺序跑这几条:

# 1. 确认 CLI 版本是你要的那个 php -v # 2. 确认加载的 php.ini 是哪个(这一步最常见问题) php -i | grep -i "loaded configuration" # 3. 确认 Laravel 真的能启动 php artisan --version # 4. 确认依赖对平台的判断 composer check-platform-reqs # 5. 确认扩展齐全(Laravel 需要这些) php -m | grep -i -E "pdo_mysql|mbstring|openssl|fileinfo|tokenizer|curl|zip"

浏览器侧用一个探测文件确认 Web 的 PHP:

<?php declare(strict_types=1); // public/php-probe.php —— 临时文件,用完删除 header('Content-Type: text/plain; charset=utf-8'); echo 'SAPI : ', PHP_SAPI, PHP_EOL; echo 'PHP 版本 : ', PHP_VERSION, PHP_EOL; echo '加载的 ini : ', (php_ini_loaded_file() ?: '(none)'), PHP_EOL; echo 'ext dir : ', ini_get('extension_dir'), PHP_EOL; echo 'pdo_mysql : ', (extension_loaded('pdo_mysql') ? '已加载' : '未加载'), PHP_EOL;

把 CLI 侧的php -v和这个探测页面显示的版本对一遍。两边一致,才算真的切好了。

实战:一条命令完成"指定版本建项目"

把前面的东西拼起来,下面这段脚本可以直接存成new-laravel.bat使用,接受一个参数作为项目目录名。它硬编码了 PHP 路径,因此不受PATH里是哪个版本影响。

@echo off setlocal rem ===== 按需修改这两个路径 ===== set "PHP_EXE=D:\phpstudy_pro\Extensions\php\php8.2.9nts\php.exe" set "COMPOSER_PHAR=D:\phpstudy_pro\Extensions\composer\composer.phar" rem ============================== if "%~1"=="" ( echo 用法: %~nx0 ^<项目目录名^> exit /b 1 ) set "APP_NAME=%~1" set "TARGET=D:\phpstudy_pro\WWW\%APP_NAME%" if exist "%TARGET%" ( echo 目录已存在: %TARGET% exit /b 1 ) echo [1/5] 检查解释器版本... "%PHP_EXE%" -v if errorlevel 1 ( echo 解释器不存在,请检查 PHP_EXE 路径 exit /b 1 ) echo [2/5] 创建项目(Laravel 12)... "%PHP_EXE%" "%COMPOSER_PHAR%" create-project laravel/laravel "%TARGET%" "^12.0" if errorlevel 1 exit /b 1 cd /d "%TARGET%" echo [3/5] 对齐平台版本... "%PHP_EXE%" "%COMPOSER_PHAR%" config platform.php 8.2.9 echo [4/5] 生成应用密钥... "%PHP_EXE%" artisan key:generate echo [5/5] 校验平台依赖... "%PHP_EXE%" "%COMPOSER_PHAR%" check-platform-reqs echo. echo 完成。网站根目录请指向: %TARGET%\public endlocal

最后那句提示很关键:Laravel 的站点根目录必须是项目的public子目录。切了 PHP 版本、装好了依赖,站点根目录指错,一样是 404。

常见坑点

坑 1:以为面板里切了 PHP 版本,命令行也跟着变了

❌ 面板里把站点切到 8.2,然后直接composer install,报requires php >=8.2

✅ 面板只管 Web 侧。CLI 侧要单独处理:显式指定解释器路径,或调整PATH顺序

坑 2:用setx改 PATH,把 PATH 截断了

❌setx PATH "%PATH%;D:\php8.2"——setx对 PATH 有长度限制,超出部分会被静默截断,PATH 直接被破坏,命令行一片混乱

✅ 用系统属性对话框改,或用 PowerShell 的环境变量接口:

$old = [Environment]::GetEnvironmentVariable('Path', 'User') [Environment]::SetEnvironmentVariable('Path', "$old;D:\php8.2", 'User')

坑 3:切了版本但没重启 Web 服务

❌ 面板里改完站点 PHP 版本直接刷浏览器,得到 502 Bad Gateway

✅ 改完面板配置后重启对应的 Web 服务(Nginx / Apache)。FastCGI 端口变了而 Web 服务器还连着旧端口,就是 502

坑 4:改了站点却始终访问不到新版本

❌ 浏览器里带缓存反复刷新,看到的一直是旧版本

✅ 用curl绕开浏览器缓存直接打探测页:

curl -s http://blog.test/php-probe.php

坑 5:把--ignore-platform-reqs当成"强制安装"的常规手段

❌ 每次装依赖都加--ignore-platform-reqs,把版本约束当噪音

✅ 用composer config platform.php 8.2.9声明目标平台,让解析在正确的约束下进行

坑 6:混用php.exe和php-cgi.exe

❌ 命令行里用php-cgi.exe跑artisan,或者反过来把php.exe配给 Web 服务器

✅ 命令行一律用php.exe(SAPI 是cli),Web 侧由 Web 服务器去调用 CGI/FPM 的可执行文件。用php -r "echo PHP_SAPI;"确认

坑 7:Composer 报内存不足,误以为是 PHP 版本问题

❌ 看到Allowed memory size exhausted就去换 PHP 版本

✅ 这是 Composer 本身的内存问题,跟版本无关:

COMPOSER_MEMORY_LIMIT=-1 composer install

坑 8:用新版本生成的composer.lock拿到旧环境上跑

❌ 在 PHP 8.4 上composer update,把composer.lock提交,然后部署到 PHP 8.2 的服务器

✅ 更新依赖前先composer config platform.php <生产版本>,让lock文件从一开始就按生产环境解析

总结

目标做法验证方式
确认 CLI 用的是哪个版本php -v/where php输出里的版本号
不依赖 PATH 跑 Composer显式指定php.exe绝对路径composer check-platform-reqs
让依赖按目标版本解析composer config platform.php 8.2.9composer show laravel/framework --all
切换 Web 侧版本面板站点设置 + 重启 Web 服务探测页显示PHP_SAPI与版本
装完 Laravel 的收尾key:generate+ 站点根指向public浏览器能打开首页和二级路由

"切了 PHP 版本没生效"这句话本身就有歧义:是 CLI 没生效,还是 Web 没生效?先分别打印两边的版本事实,再决定改哪一处。最省心的长期方案是放弃依赖PATH,在项目里放一个固定解释器路径的包装脚本,让"用哪个 PHP"变成项目的一部分而不是环境的一部分。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询