
本文介绍如何让“random story”按钮根据文本文件中真实的故事数量(而非预设最大值)动态生成1到实际总数之间的随机故事编号,避免越界错误。
本文介绍如何让“random story”按钮根据文本文件中真实的故事数量(而非预设最大值)动态生成1到实际总数之间的随机故事编号,避免越界错误。
在当前实现中,country.js 通过硬编码的 actualTotalStories(如 'usa': { ..., actualTotalStories: 1000 })控制随机数范围,而 router.php 却在运行时通过 count($stories) 动态计算真实故事数——两者不一致导致逻辑错位:JavaScript 端按 1000 生成随机数,但 PHP 端仅支持最多 6 个故事,造成频繁 404 或“故事不存在”错误。
要彻底解决该问题,关键原则是:随机逻辑应完全由服务端决定,前端仅触发请求,不参与范围计算。这样既能保证准确性,又避免前后端状态同步风险。
✅ 正确做法:移除前端硬编码,交由 PHP 动态判定
-
修改 country.js —— 简化随机请求逻辑
不再传递 '0' 并依赖前端计算,而是直接向 PHP 发起无 story 参数的请求(或显式传 'random'),由后端统一处理:
if (getRandomButton) {
getRandomButton.addEventListener('click', function () {
// 发起不带 story 参数的请求 → 触发 PHP 随机逻辑
fetch(`PHP/router.php?country=${encodeURIComponent(country)}`)
.then(response => {
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.text();
})
.then(data => {
clearStoryContainer();
document.getElementById('generated-text').innerHTML = parseAndStyleTitles(data);
document.getElementById('story-container').style.display = 'block';
document.getElementById('back').style.display = 'inline-block';
})
.catch(err => {
console.error('Failed to fetch random story:', err);
displayErrorMessage('Failed to load random story.');
});
});
}
-
重构 router.php —— 统一随机与指定逻辑
移除对 story=0 的特殊处理,改为:当 $_GET['story'] 未设置或为空/非法时,自动计算并选取随机故事:
<?php header('Content-Type: text/html; charset=utf-8');
if (!isset($_GET['country'])) {
die('Invalid request.');
}
$country = $_GET['country'];
$validCountries = [
'argentina' => 'argentina.txt',
'usa' => 'usa.txt',
'sweden' => 'sweden.txt',
];
if (!isset($validCountries[$country])) {
die('The requested country does not exist.');
}
$filePath = '../../Stories/' . $validCountries[$country];
if (!file_exists($filePath)) {
die('The story file does not exist.');
}
$contents = file_get_contents($filePath);
$stories = preg_split('/<!-- Unique delimiter separating stories -->/', $contents, -1, PREG_SPLIT_NO_EMPTY);
$actualCount = count($stories);
// ✅ 核心改进:动态决定 storyNumber
if (isset($_GET['story']) && is_numeric($_GET['story']) && $_GET['story'] >= 1 && $_GET['story']
⚠️ 注意事项:
- nl2br() 自动将 \n 转为
,比手动 str_replace 更健壮;- htmlspecialchars() 防止 XSS,尤其当故事内容含用户输入时必不可少;
- PREG_SPLIT_NO_EMPTY 避免因分隔符位置不当产生空元素;
- 前端 fetch() 替代 XMLHttpRequest 提升可读性与 Promise 支持。
✅ 最终效果
- 无论 usa.txt 当前含 6 条还是 999 条故事,点击“Random Story”始终返回 1–N 中的有效随机故事;
- “Get Story” 输入框仍支持手动输入(如 7),且自动校验合法性;
- 前端不再维护 actualTotalStories,消除数据冗余与同步隐患;
- 扩展新国家时,只需在 $validCountries 中添加映射,无需修改逻辑。
这种服务端驱动的设计更可靠、更易维护,是 Web 应用中处理动态数据范围的标准实践。











