安装向导 + PHP 8.5 兼容修复
新增 install.php:全新部署时自动接管,用户只需上传文件、打开站点即进入
安装向导。安装页自己做三件事:
- 建 db/ 与 uploads/{posters,tickets,photos,avatars}/,权限调到 775
- 逐目录真写临时文件实测可写,不靠 is_writable 猜
- 建库、建管理员、写 db/.installed 锁、自删本文件
配套改动:
- config.php 把安装检查前置于建库之前,未安装一律 302 到 install.php。
原实现无条件调用 initDB(),导致「打开首页」就等于建库并种下 admin/123456。
- lib/db.php 的 initDB(\$seedDefaultAdmin = true);安装向导传 false,
管理员由用户自己设,绝不种弱口令。新增 isInstalled()。
- login.php / nav.php 接上 siteName(),站点名称不再只存不用。
- lib/settings.php 新增 siteName(),缺省回退「电影日志」。
PHP 8.5 兼容:
- 删掉 fetch_movie.php 与 lib/storage/http.php 的 curl_close()。
8.5 起该函数 deprecated,调用会往输出插一行警告,把 JSON 响应污染成
「警告 + JSON」,前端 JSON.parse 失败 → 电影名联想功能完全失灵。
- config.php 的 display_errors 由 1 改为 0(生产环境不应向浏览器吐错误),
错误仍写日志;需要调试时设 MOVIELOG_DEBUG=1 打开。
线上验证(movie.yangyq.net,PHP 8.5.12):
未安装时 / 、/login.php 均 302 → install.php;
安装页 200、体检 10/10 通过、自动建好 5 个目录;
安装后 install.php 404、管理员登录成功、首页 200 无报错;
联想接口带会话请求「流浪地球/星际穿越/霸王别姬」均返回纯 JSON(首字符 {)。
This commit is contained in:
+42
-2
@@ -6,8 +6,25 @@
|
||||
// 所有页面统一通过 require_once 'config.php' 引入本文件。
|
||||
// ============================================
|
||||
|
||||
// 错误报告策略。
|
||||
//
|
||||
// 关键:PHP 的警告/弃用提示是**直接写进响应体**的。对返回 JSON 的接口
|
||||
// (fetch_movie.php、storage_api.php 等)来说,一条 Warning 插在 JSON 前面
|
||||
// 就会让前端 JSON.parse 失败,表现为「功能静默失灵」——联想下拉空着、
|
||||
// 存储测试报连接失败,都可能是这个原因,而接口本身其实是好的。
|
||||
//
|
||||
// 本项目踩过:PHP 8.5 把 curl_close() 标为 deprecated,一行提示就把
|
||||
// 「电影名联想」整个搞挂了(接口返回的 JSON 完全正确,只是前面多了警告)。
|
||||
//
|
||||
// 因此:
|
||||
// - 永远不把错误显示给浏览器(display_errors=0);
|
||||
// - 仍然记录到日志(log_errors=1),排查时看 PHP 错误日志;
|
||||
// - 需要临时调试时,设环境变量 MOVIELOG_DEBUG=1 即可把错误显示打开。
|
||||
$__movielog_debug = getenv('MOVIELOG_DEBUG') === '1';
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_errors', $__movielog_debug ? '1' : '0');
|
||||
ini_set('log_errors', '1');
|
||||
unset($__movielog_debug);
|
||||
|
||||
session_start();
|
||||
|
||||
@@ -38,6 +55,27 @@ foreach ([POSTER_DIR, TICKET_DIR, PHOTO_DIR, AVATAR_DIR] as $dir) {
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 安装检查(必须在加载任何业务模块、建库之前)=====
|
||||
//
|
||||
// 未安装时:把请求引到 install.php,并立刻退出 —— 绝不能继续往下走到 initDB()。
|
||||
// 判据只看锁文件 db/.installed,由 install.php 装完时写入。
|
||||
//
|
||||
// 为什么不能「先 initDB() 再判断」:
|
||||
// initDB() 会建库建表,并在 admins 为空时插入 admin/123456。
|
||||
// 那样「打开任意页面」这个动作就等于完成了一半安装,还会把弱口令暴露出去
|
||||
// (FeedLite 踩过同一个坑:访问动作本身建库 → 「未安装」永远判不出来)。
|
||||
//
|
||||
// 例外:install.php 自身、以及 css/js 等静态资源不受此检查约束
|
||||
// (install.php 不加载本文件;静态资源由 Web 服务器直接返回,不经过 PHP)。
|
||||
if (!is_file(ROOT_DIR . '/db/.installed')) {
|
||||
// 当前脚本名(兼容子目录部署)
|
||||
$self = basename($_SERVER['SCRIPT_NAME'] ?? '');
|
||||
if ($self !== 'install.php' && PHP_SAPI !== 'cli') {
|
||||
header('Location: install.php');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 功能模块 =====
|
||||
require_once ROOT_DIR . '/lib/db.php'; // 数据库连接与初始化
|
||||
require_once ROOT_DIR . '/lib/settings.php'; // 系统设置读写
|
||||
@@ -50,4 +88,6 @@ require_once ROOT_DIR . '/lib/reviews.php'; // 评价与评价下的讨论
|
||||
require_once ROOT_DIR . '/lib/stats.php'; // 统计与年度报告
|
||||
|
||||
// 初始化数据库
|
||||
initDB();
|
||||
// 走到这里说明已装过(上面的检查已拦截未安装的情况),
|
||||
// 因此 seedDefaultAdmin 传 false:老库本来就有人,空库也不该被塞一个 admin/123456。
|
||||
initDB(false);
|
||||
|
||||
Reference in New Issue
Block a user