我在 Windows 上开发,服务器是 Ubuntu。两边的差异不大,但每一处都足够让「本地能跑」变成「线上白屏」。记录踩过的坑和对应的取舍。
第一,文件名大小写。
Windows 文件系统默认不区分大小写,Admin.php 和 admin.php 在本地是同一个文件;Linux 严格区分,require 时一个字母大小写不对直接致命错误。对策很简单:所有文件名一律小写,严格保持一致,不要在这件事上发挥想象力。
第二,路径分隔符。
代码里所有路径统一用正斜杠 /,不要用 Windows 的反斜杠。PHP 自身在 Windows 上也能正确识别 /,这样代码天然跨平台。拼路径的地方都走 dirname(__FILE__) 或项目根常量,不写死盘符。
第三,换行符和编码。
所有文件统一 UTF-8 无 BOM、LF 换行。Windows 编辑器默认 CRLF 会带来两个问题:shell 脚本的首行 shebang 解析失败,以及跨平台 diff 噪音。我在编辑器里全局设置 LF,并写了一个脚本批量检查。
第四,PHP 内置服务器和生产服务器的路由不一样。
本地用 php -S localhost:8000 router.php,router.php 负责把不存在的文件路径交给 index.php,并拦截敏感目录。线上是 Nginx + PHP-FPM,由 try_files 实现同样的转发。两套路由逻辑必须保持等价,否则会出现「本地 404 正常、线上下载 PHP 文件」这类诡异问题。
第五,后台路径被当静态文件下载。
这是我实际踩过的坑:Nginx 里 location ^~ /admin 配了 try_files,而 /admin 这个路径对应不到磁盘文件时,Nginx 会尝试把 admin.php 当静态文件返回给浏览器,浏览器就触发了下载。正确做法是 /admin 这个 location 直接交给 PHP-FPM 处理,或者明确 try_files 到 /admin.php。
第六,数据库和敏感文件不能放在网站根目录。
SQLite 文件放在 storage/ 目录,而 storage/ 在 public/ 之外,Nginx 根本访问不到。本地的 router.php 也做了同样的拦截。本地和线上都要靠规则,不能只靠「目录深一点」。
第七,权限。
Linux 上 PHP-FPM 以 www-data 用户运行,storage/ 目录需要可写;代码目录则保持只读,防止 Web 进程被利用后改写源码。最小权限原则:只有 uploads 和 storage 能写,其他地方一概不给。
取舍的核心就一句话:把「跨平台」写进代码规范,而不是写进部署时的祈祷。
能靠命名规范解决的,就不要靠运气;能本地和线上用同一套规则的,就不要维护两套。
评论(0)
还没有评论。