本地环境搭了八遍才跑通,原来我第一步就把目录结构抄错了
昨天帮一个刚入坑的朋友看项目,他发过来的截图让我愣了三秒——index.php 和 vendor 平躺在桌面文件夹里,public 目录是他后来"觉得应该有个放图片的地方"手动新建的。这场景太熟悉了,三年前我也是这么干的。
那时候跟着某教程学 ThinkPHP,视频里讲师轻飘飘一句"把代码放到 web 目录",我就真把整个项目包丢进了 Nginx 的 root。能跑吗?能跑。安全吗?直到我在日志里看到有人直接访问 /application/database.php 才后知后觉。
目录结构不是"约定俗成",是"物理隔离"
现在每次开新项目,我会先画个草图给自己看:
project/ ├── app/ ← 应用逻辑,对外不可见 ├── config/ ← 配置文件,对外不可见 ├── extend/ ← 扩展类库,对外不可见 ├── public/ ← ← ← 唯一对外开口 │ ├── index.php ← 入口文件,仅此一个 │ ├── static/ ← 编译后的 CSS/JS │ └── uploads/ ← 用户上传(注意权限) ├── runtime/ ← 缓存日志,对外不可见 └── vendor/ ← 依赖包,对外不可见
关键点就一条:web 服务器只认 public,其他目录对它来说不存在。 不是"建议",是"必须"。Nginx 配置里那个 root /var/www/project; 改成 root /var/www/project/public; 的瞬间,才算真正入门。
入口文件那几行,我抄了半年没看懂
TP6 的 public/index.php 默认长这样:
<?php require __DIR__ . '/../vendor/autoload.php'; $http = (new \think\App())->http; $response = $http->run(); $response->send(); $http->end();
有段时间我嫌它"不够简洁",自己改成了:
<?php require '../vendor/autoload.php'; (new \think\App())->run();
本地能跑,上线就 500。查了半天才发现,__DIR__ 和相对路径在 CLI 模式和 FPM 模式下解析结果可能不同,而 $http->end() 负责清理连接池和日志写入,少了它高并发下会漏日志。现在我再也没动过官方模板,看不懂的先留着,比"优化"后埋雷强。
本地环境我现在的偷懒三件套
早期我坚持用"原生"环境:本机装 Nginx、PHP、MySQL,版本自己配,扩展自己编,一个下午能搭好算快的。现在?
Windows: Laragon,绿色版,PHP 版本下拉切换,自带 Mail Catcher 和 Redis,数据库文件直接躺在项目旁边,重装系统拷走文件夹就行。
Mac: Herd 或者继续 Laragon 的 WSL2 方案。Herd 的坑是默认 PHP 版本偏新,老项目得手动指定,但 herd link 秒配本地域名确实香。
统一习惯: 每个项目配一个 .env.local,数据库名带 _dev 后缀,上传目录软链到 storage/app/public,绝不直接往 public/uploads 写东西——防止某天手滑把本地测试图同步到生产环境。
一个让我红温的调试细节
TP6 默认开启 app_debug 时,报错页面会暴露绝对路径。本地无所谓,但有一次我截图发群求助,朋友秒回:"你用户名是 realname 啊?"
现在我的 .env.local 里固定加两行:
APP_DEBUG = true APP_TRACE = false
调页面用 debug,但关闭右侧那个详细的请求追踪面板——它会把 SQL 参数、Session ID 全摊开来。本地也不是法外之地,养成肌肉记忆,上线才不会忘。
你们本地环境现在还折腾吗?我观察到一个现象:老站长越来越懒,新站长越来越爱"从零编译"。可能踩过坑才知道,能跑起来的环境才是好环境,至于它底层是 Docker、WSL 还是远古的 phpStudy,真没那么重要。