ThinkPHP跨平台部署需统一入口路径、PHP环境和域名识别逻辑;public目录必须设为Web根目录,PHP版本与扩展在CLI和Web下须一致,.env仅开发时生效,生产环境应使用服务器级环境变量,本地开发需同步域名配置,runtime目录权限需同时允许Web与CLI用户写入。

ThinkPHP跨平台部署不是换个系统重装一遍,而是让同一套代码在Windows开发、Linux上线、Docker容器甚至Mac M1/M2上都能稳定运行。核心不在“兼容”,而在“统一关键路径和行为逻辑”。只要三件事对齐:入口路径一致、PHP环境一致、域名与会话识别逻辑一致,跨平台就基本不会翻车。
public目录必须设为Web根目录
这是所有失败的起点。ThinkPHP 6+采用前端控制器模式,所有HTTP请求必须经public/index.php统一入口。若把整个项目(含app/、config/)直接扔进/var/www/html或htdocs,会导致:
- 敏感目录如config/、app/被直接访问,源码泄露风险极高
- vendor/autoload.php路径错位,报Class 'think\App' not found
- 静态资源(如public/static/)404,CSS/JS全部失效
实操要点:
- Apache:DocumentRoot指向项目/public目录,并确保对应
块中AllowOverride All已启用 - Nginx:root指令写成root /var/www/myapp/public;,不是项目根目录;别用root /var/www/myapp;
- 宝塔面板:站点设置 → 根目录 → 手动改为public子目录
- 本地Windows开发:cd public后执行php -S localhost:8000 router.php,而非在项目根目录启动
PHP版本与扩展必须双环境一致
CLI(命令行)和Web(FPM/Apache)两个SAPI下,PHP版本和关键扩展必须完全一致。常见问题:php -v显示8.2,但Nginx跑起来却报502或白屏——往往是因为php-fpm调用的是另一份PHP二进制。
验证方式(两处都要跑):
- 终端执行:php -v 和 /usr/bin/php-fpm82 -v(路径以ps aux | grep php-fpm查到的实际为准)
- 浏览器访问phpinfo()页面,确认openssl、gd、mbstring、session、pdo_mysql、fileinfo均已启用
- 若CLI有而Web无,说明Nginx加载了不同php.ini:对比php --ini和phpinfo()中的“Loaded Configuration File”路径
安装建议:
- Ubuntu:sudo apt install php8.2 php8.2-fpm php8.2-mysql php8.2-mbstring php8.2-gd php8.2-xml php8.2-curl php8.2-opcache php8.2-fileinfo
- CentOS 8+/Rocky:sudo dnf module enable php:remi-8.2 && sudo dnf install php php-mysqlnd php-mbstring php-gd php-xml php-curl php-opcache php-fileinfo
.env文件生效机制与生产环境替代方案
.env不生效?大概率不是配置错了,而是框架根本没读它。ThinkPHP 6+默认只在APP_DEBUG = true且运行于CLI或FPM开发模式时自动加载.env;生产环境(APP_DEBUG = false)直接跳过,用config/里的硬编码值。
正确做法:
- 开发阶段:export APP_DEBUG=true(Linux/macOS)或set APP_DEBUG=true(Windows),再运行php think命令
- 生产环境:不要依赖.env存数据库密码等敏感信息,改用服务器级环境变量:Nginx中加fastcgi_param DB_HOST "127.0.0.1";,Docker中用environment: - DB_HOST=127.0.0.1,代码里用Env::get('DB_HOST')
- .env文件必须放在项目根目录(与think可执行文件同级),命名只能是.env,不能是.env.local或.env.production
二级域名与本地开发环境行为同步
本地用localhost,线上用admin.example.com,路由直接fallback——因为ThinkPHP靠$_SERVER['HTTP_HOST']判断域名,而localhost永远不匹配任何子域名规则。
统一方案:
- hosts文件添加:127.0.0.1 admin.example.com api.example.com example.com
- Nginx server_name写成*.example.com example.com(通配支持所有子域)
- 禁用app_host等CLI专属配置,启用url_domain_deploy => true(TP6)或APP_SUB_DOMAIN_DEPLOY => 1(TP5)
- 路由定义用显式+兜底组合:Route::domain('admin', ...) + Route::domain('*', ...),避免依赖APP_DOMAIN_SUFFIX等后缀推导
runtime目录权限与用户归属
runtime是ThinkPHP的“工作台”:日志、缓存、模板编译、验证码图片全存在这里。若权限不对,轻则500错误,重则功能静默失效(比如验证码总提示错误)。
关键细节:
- runtime目录需同时被Web进程用户(如www-data、nginx)和CLI用户(如deploy、root)写入
- 推荐做法:chown -R www-data:www-data runtime && chmod -R 775 runtime
- 若CLI用户不是www-data,加用户到www-data组:usermod -aG www-data deploy
- 部署后清空runtime/子目录(log/cache/template),避免旧缓存干扰
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











