ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

PHP星座运势查询系统开发实战:边界判定、安全防护与性能优化

PHP星座运势查询系统开发实战:边界判定、安全防护与性能优化 简介PHP星座运势查询系统源码是一份面向Web初学者的实战型项目适合用于毕业设计、课程设计或个人技术练习。系统围绕用户出生日期输入、星座自动匹配计算、运势数据查询与结果展示等完整业务环节清晰演示了PHP项目从表单交互、逻辑计算、数据库读取到页面渲染的典型Web开发流程。压缩包为zip格式大小474KB包含多份PHP后端业务逻辑文件、前端页面样式脚本及数据库初始化SQL脚本等文件类型目录结构清晰便于模块化阅读和二次开发。代码中实际涉及$_GET/$_POST请求参数接收、date()与strtotime()日期运算、PDO数据库预处理查询、SQL注入与XSS安全防护、异常处理与日志记录等关键知识点拿到源码后可直接搭建运行不仅能直观体验星座匹配与运势展示效果还可以顺藤摸瓜理解PHP的MVC分层思路与完整业务闭环并进一步扩展用户注册登录、运势订阅推送等功能。目前已有300人浏览/学习该资源对于需要快速参考PHP实战写法和上手的开发者有较好的借鉴价值。1. 星座判定不止是日期比较这个 PHP 项目的边界坑与实战拆解拿到这份 PHP 星座运势查询系统源码第一反应是逻辑应该很简单——把出生日期映射到星座查表返回运势文本就行。但真正拆过这类项目的人都知道最容易出问题的不在查询语句而在星座日期边界的处理上。12 个星座的切换日期分布在每月不同时段比如双子座和巨蟹座的交界在 6 月 21 日或 22 日前后不同年份还有细微差异如果只用简单的 if-else 字符串比较很容易在边界日期上判错。这个项目适合两类人刚学完 PHP 语法、想完整走一遍 Web 请求到数据库返回全流程的初学者以及需要快速搭一个内容型查询站点、后续要接用户系统和缓存层的开发者。下文按实际开发顺序从星座计算核心逻辑开始逐步拆到数据表设计、运势内容组织、安全防护和部署细节。2. PHP 星座计算的日期边界与逻辑实现2.1 星座日期范围的数据结构设计星座判定最稳妥的做法不是硬编码大量 if-else而是把 12 个星座的日期范围定义成结构化数组。每个星座需要三个关键字段名称、起始月日、结束月日。这里有一个容易被忽略的点星座日期的判定只依赖月和日与年份无关所以用四位数字表示月日如 0321 表示 3 月 21 日可以简化比较逻辑。但要特别注意跨年情况魔羯座从 12 月 22 日到次年 1 月 19 日如果使用简单的日期范围比较需要单独处理跨越年度的区间这是初学者最容易写错的地方。比较稳妥的方案是使用 PHP 的DateTime类把用户的出生日期和星座的起始结束日期都格式化为四位字符串进行比较。这种做法的稳定之处在于format(md)函数天然返回两位月两位日的固定格式比如 1 月 5 日返回0105直接用字符串比较大小即可省去了整型转换的麻烦。对于跨年星座将判定逻辑分成两段 1222或 0119命中任意一段都归入魔羯座。这样做代码可读性更高后续如果要调整星座日期范围比如某些流派对天蝎座日期有不同划分只需修改数组中的一个元素即可。2.2 星座判定函数的完整实现下面给出一个可直接用于生产环境的星座判定函数使用 PHP 原生语法不依赖第三方库?php function determineZodiac(string $birthday): array { $birth new DateTime($birthday); $md $birth-format(md); $zodiacs [ [name 水瓶座, start 0120, end 0218], [name 双鱼座, start 0219, end 0320], [name 白羊座, start 0321, end 0419], [name 金牛座, start 0420, end 0520], [name 双子座, start 0521, end 0621], [name 巨蟹座, start 0622, end 0722], [name 狮子座, start 0723, end 0822], [name 处女座, start 0823, end 0922], [name 天秤座, start 0923, end 1023], [name 天蝎座, start 1024, end 1122], [name 射手座, start 1123, end 1221], [name 魔羯座, start 1222, end 0119], ]; foreach ($zodiacs as $zodiac) { if ($zodiac[start] $zodiac[end]) { // 非跨年星座直接比较 if ($md $zodiac[start] $md $zodiac[end]) { return $zodiac; } } else { // 跨年星座魔羯座分两段判断 if ($md $zodiac[start] || $md $zodiac[end]) { return $zodiac; } } } return [name 未知星座, start , end ]; }这段代码的重点在于跨年星座的判断分支。start大于end时魔羯座 1222 到 0119说明该星座跨越了年份边界此时不能直接执行区间比较而应使用逻辑或用户日期大于等于起始日或小于等于结束日均命中。参数方面$birthday接受YYYY-mm-dd格式字符串这是 HTML5 日期输入框date类型的默认提交格式。返回的数组直接包含星座名称和边界值后续查询运势数据时可以直接使用name字段作为查询条件。2.3 表单校验与无效日期的兜底处理用户输入不可能总是规范的。常见问题包括格式错误、明显不存在的日期如 2 月 30 日、空值提交等。PHP 的DateTime类在解析非法日期时不会主动抛异常而是返回false因此必须显式校验。推荐做法是先校验格式再校验日期有效性?php $input $_POST[birthday] ?? ; if (!preg_match(/^\d{4}-\d{2}-\d{2}$/, $input)) { die(日期格式不正确请使用 YYYY-mm-dd 格式); } $dateParts explode(-, $input); if (!checkdate((int)$dateParts[1], (int)$dateParts[2], (int)$dateParts[0])) { die(您输入的日期不存在请检查月份和日期); }preg_match只检查格式模板无法识别语义错误必须配合checkdate做实际日期验证。checkdate接收月、日、年三个整型参数返回布尔值能正确处理闰年 2 月 29 日等特殊情况。这一步做得好后续DateTime实例化时就不会遇到解析异常。在实际项目里我会同时对$_GET和$_POST两个来源做同样的处理避免用户通过修改请求方式绕过前端校验。3. 数据库设计与 PHP 数据访问层搭建3.1 星座运势表的字段规划与 SQL 初始化星座运势系统的数据库设计不需要太复杂但字段规划要预留扩展空间。基础表zodiac_fortune至少需要包含星座名称、运势日期类型daily/weekly/monthly、具体日期范围、整体运势评分、幸运色、幸运数字、爱情运势文本、事业运势文本、健康运势文本、财运文本。如果后续要接天气、黄历或节日数据还要考虑关联字段。这里给出初始建表 SQLCREATE TABLE zodiac_fortune ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, zodiac_name VARCHAR(10) NOT NULL COMMENT 星座名称, fortune_type ENUM(daily,weekly,monthly) NOT NULL DEFAULT daily, start_date DATE NOT NULL COMMENT 运势起始日期, end_date DATE NOT NULL COMMENT 运势结束日期, overall_rating TINYINT NOT NULL DEFAULT 3 COMMENT 综合运势评分 1-5, lucky_color VARCHAR(20) DEFAULT COMMENT 幸运色, lucky_number VARCHAR(10) DEFAULT COMMENT 幸运数字, love_text TEXT COMMENT 爱情运势, career_text TEXT COMMENT 事业运势, health_text TEXT COMMENT 健康运势, wealth_text TEXT COMMENT 财运运势, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_zodiac_date (zodiac_name, fortune_type, start_date) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT星座运势内容表;字段类型的选择有讲究。fortune_type使用ENUM而不是VARCHAR原因是枚举类型在数据库层面就能限制取值范围避免程序写入非法类型。overall_rating使用TINYINT即可评分区间 1 到 5不需要INT浪费空间。联合索引idx_zodiac_date覆盖了按星座和日期类型查询的最常见场景。updated_at使用ON UPDATE CURRENT_TIMESTAMP每次更新自动刷新省去应用层手动维护。3.2 PDO 预处理连接与查询实现数据库访问推荐使用 PDO 扩展而不是mysqli原因是 PDO 支持预处理语句、命名参数和多种数据库驱动切换数据库时改动最小。连接配置独立成文件生产环境关闭错误展示开发环境开启异常捕获?php // config.php define(DB_HOST, 127.0.0.1); define(DB_NAME, zodiac_db); define(DB_USER, root); define(DB_PASS, your_password); define(DB_CHARSET, utf8mb4); try { $dsn sprintf(mysql:host%s;dbname%s;charset%s, DB_HOST, DB_NAME, DB_CHARSET); $pdo new PDO($dsn, DB_USER, DB_PASS, [ PDO::ATTR_ERRMODE PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES false, ]); } catch (PDOException $e) { error_log(Database connection failed: . $e-getMessage()); exit(系统繁忙请稍后再试); }关键参数说明PDO::ATTR_EMULATE_PREPARES设为false时PDO 使用 MySQL 原生预处理避免模拟预处理带来的 SQL 注入风险PDO::ATTR_ERRMODE设为ERRMODE_EXCEPTION让数据库错误以异常形式抛出配合try-catch统一处理。FETCH_ASSOC返回关联数组字段名访问比数字索引更可读。查询运势数据时按星座名称和日期类型作为条件并限制日期范围包含当前日期?php function getDailyFortune(PDO $pdo, string $zodiacName, string $today ): array { $today $today ?: date(Y-m-d); $stmt $pdo-prepare( SELECT * FROM zodiac_fortune WHERE zodiac_name :zodiac AND fortune_type daily AND start_date :today AND end_date :today ORDER BY start_date DESC LIMIT 1 ); $stmt-execute([:zodiac $zodiacName, :today $today]); return $stmt-fetch() ?: []; }这里为什么用ORDER BY start_date DESC LIMIT 1因为同一星座在一年内可能有多条日运记录比如按周批量生成时今天可能命中上周和本周两条记录排序取最近一条保证结果唯一。如果数据表为空fetch()返回false三元表达式兜底为空数组前端展示时做默认处理避免模板变量未定义报错。3.3 运势内容的生成与批量入库策略运势数据不应每请求一次就生成一次那样既消耗 CPU 又难以保持一致体验。合理的做法是后台脚本每日或每周批量生成写入数据库前端只读。生成方式可以是预设文本库随机组合也可以接入现成的运势 API。这里介绍一种不依赖外部服务的文本模板组合方式?php $templates [ love [ 单身者有机会在{place}遇到让你心动的人主动一点会加分。, 有伴侣者适合安排一次短途旅行共同体验新鲜事物。, ], career [ 工作中注意细节{time}前后可能有一个重要的汇报节点。, 团队协作运佳适合推进需要多方配合的项目。, ], ]; function generateFortuneText(string $type, string $place 咖啡馆, string $time 下午): string { global $templates; $pool $templates[$type] ?? []; if (empty($pool)) { return 运势平稳按部就班即可。; } $text $pool[array_rand($pool)]; $text str_replace([{place}, {time}], [$place, $time], $text); return $text; }array_rand从模板池随机取一条配合str_replace填充动态变量让每天的文本有变化但不完全随机。global $templates只是为了演示实际项目中应该把模板放在独立配置文件中或者存入数据库模板表后台管理界面可编辑。评分字段overall_rating可以用随机数生成范围为 3 到 5避免低评分太多影响用户体验但这属于运营策略而非技术限制。批量入库时使用预处理语句循环执行每 500 条事务提交一次避免长事务锁表。一次性生成一个月的数据按今天日期循环填充start_date和end_date每天为 12 个星座各生成一条记录。生成脚本通过cron定时执行常见做法是每天凌晨 1 点跑一次确保用户早上访问时数据已就绪。4. 前端交互实现与 XSS 防护边界4.1 用户输入回显与htmlspecialchars的正确姿势用户的出生日期通常不需要回显到页面但星座名称、运势文本等内容是从数据库读取的理论上安全。真正需要防范的是未来扩展的场景比如用户自定义昵称、评论功能、分享文案等。在这些场景下所有输出到 HTML 的内容都必须经过转义。PHP 提供了htmlspecialchars函数但很多开发者只传入第一个参数忽略了后续参数的重要性?php function e(?string $value): string { return htmlspecialchars($value ?? , ENT_QUOTES | ENT_SUBSTITUTE, UTF-8); }ENT_QUOTES同时转义单引号和双引号防止属性值注入ENT_SUBSTITUTE替代无效的 UTF-8 编码序列避免输出乱码。自定义e()函数的目的是统一转义入口模板中写? e($fortune[love_text]) ?比手动调用htmlspecialchars更规范后续如果要改用htmlpurifier之类更严格的过滤器只需修改这一个函数。4.2 日期选择组件与 AJAX 请求的处理前端交互不复杂核心是让用户选择出生日期提交后在同一页面刷新运势结果。HTML5 的input typedate在 Chrome、Edge、Firefox 等主流浏览器中体验一致移动端会调起原生日期选择器。这里需要注意 PHP 端接收到的日期格式是固定的YYYY-mm-dd不需要做多余处理。但考虑到部分老版本 Safari 对date类型支持不完整建议加一个pattern属性和前端初步校验input typedate namebirthday required min1920-01-01 max? date(Y-m-d) ? pattern\d{4}-\d{2}-\d{2} title请选择出生日期min和max限制了可选范围避免用户提交未来日期或超过 100 岁的日期。pattern属性在date类型下虽然没有实际效果但保留它可以提升代码的自解释性。提交可以走传统表单刷新也可以走 AJAX。走 AJAX 时PHP 端返回 JSON 格式的运势数据前端用fetch接收并局部更新 DOM?php // ajax_handler.php header(Content-Type: application/json; charsetutf-8); $birthday $_POST[birthday] ?? ; $zodiacInfo determineZodiac($birthday); if ($zodiacInfo[name] 未知星座) { http_response_code(400); echo json_encode([error 无法判定星座请检查输入日期]); exit; } $fortune getDailyFortune($pdo, $zodiacInfo[name]); echo json_encode([ zodiac $zodiacInfo[name], fortune $fortune, server_time date(Y-m-d H:i:s), ]);header(Content-Type: application/json)必须放在任何输出之前否则 JSON 响应会携带 PHP 警告或错误信息前端res.json()解析失败。http_response_code(400)用于标识客户端输入错误方便前端统一拦截处理。date(Y-m-d H:i:s)返回服务器当前时间可以用于调试时确认响应是否来自缓存。4.3 无数据时的降级展示逻辑数据库中没有对应日期的运势数据时不能直接抛错或展示白屏。降级策略分两级先尝试返回最近一条历史运势再不行就返回预设默认文本。这个逻辑可以封装在查询函数内部调用方无需感知数据缺失?php function getFortuneSafe(PDO $pdo, string $zodiacName): array { $today date(Y-m-d); $fortune getDailyFortune($pdo, $zodiacName, $today); if (!empty($fortune)) { return $fortune; } // 降级一查询最近一条历史运势 $stmt $pdo-prepare( SELECT * FROM zodiac_fortune WHERE zodiac_name :zodiac AND fortune_type daily AND end_date :today ORDER BY end_date DESC LIMIT 1 ); $stmt-execute([:zodiac $zodiacName, :today $today]); $history $stmt-fetch(); return $history ?: [ zodiac_name $zodiacName, fortune_type daily, overall_rating 3, lucky_color 白色, lucky_number 7, love_text 今日运势数据准备中保持平和心态一切都会如期而至。, career_text 按计划推进手头工作避免临时改变节奏。, health_text 注意规律作息适当补充水分。, wealth_text 理性消费避免冲动决策。, ]; }这种降级逻辑的核心价值在于数据库维护人员清空表数据重建时线上页面不会立刻出现空白或 500 错误而是展示默认文本从用户视角看只是内容模板化程度高一些。end_date :today条件确保只查询过去的记录避免查到未来计划插入但已预生成的数据。5. 安全加固SQL 注入、XSS 与 PHP 版本兼容性5.1 SQL 注入防护的常见误区和预处理正确用法PHP 项目中 SQL 注入的高发点通常不在主查询而在排序字段、分页偏移量、模糊搜索关键词等动态拼接处。以排序字段为例如果代码如下ORDER BY {$_GET[sort]}即使使用 PDO 预处理也无济于事因为预处理只能绑定值不能绑定表名、字段名或ORDER BY方向。处理白名单是最稳妥的方案?php $allowedSort [start_date ASC, overall_rating DESC, id DESC]; $sortKey $_GET[sort] ?? start_date; $sortDirection $allowedSort[$sortKey] ?? DESC; // 这样生成 SQLORDER BY start_date DESC$allowedSort白名单同时控制了字段和方向任何不在数组中的值都会落到默认值DESC。这种做法比黑名单过滤更安全因为黑名单难以穷尽所有攻击载荷。另一类常见问题是直接把$_POST[keyword]拼接到LIKE语句中即使开发者使用了addslashes在高版本 PHP 下仍可能被宽字节注入绕过。预处理加参数绑定的方式可以彻底解决这个问题SELECT * FROM zodiac_fortune WHERE love_text LIKE :keyword执行时传入[:keyword % . $keyword . %]%通配符属于数据的一部分不参与 SQL 解析不存在注入风险。这里要注意PDO::ATTR_EMULATE_PREPARES必须为false否则 PDO 内部将预处理替换为转义拼接虽然大多数场景安全但边界情况不如原生预处理可靠。5.2 XSS 攻击面分析与 CSP 响应头配置星座运势系统本身输出内容大多来自数据库XSS 风险低于论坛、博客等 UGC 应用。但当后台管理系统开放后运营人员录入的运势文本如果包含script标签就会形成存储型 XSS。防御分两层输入侧过滤不为最优方案因为业务上有时需要允许部分 HTML 标签输出侧转义必须做到无死角。推荐组合是前端模板转义加响应头 CSP 限制?php header(Content-Security-Policy: default-src self; script-src self; style-src self unsafe-inline; img-src self data:);script-src self禁止加载任何外部域名的 JavaScript 文件即使数据库内容被注入script srchttp://evil.com/x.js浏览器也会拒绝加载。style-src unsafe-inline为避免内联样式被拦截破坏布局而保留如非必要可以移除。img-src self data:允许 base64 图片方便未来运势配图功能但不允许外链图片。CSP 是纵深防御的重要组成部分即使输出转义被遗漏攻击脚本也无法执行。5.3 PHP 版本兼容与date()参数在 PHP 8 下的变化PHP 8.0 起date()的时区参数已经废弃传参会触发Deprecated警告。不少从老项目迁移的代码仍然使用date(Y-m-d, strtotime($input))这种写法。strtotime的解析能力很强但有时会产生意外结果比如strtotime(2023-02-31)不会报错而是自动进位到 3 月 3 日这会导致星座判定错误。规范做法是先验证日期合法性再转换?php $timestamp strtotime($birthday); if ($timestamp false) { die(无效的日期格式); } // 验证是否进位回格式化检查是否一致 if (date(Y-m-d, $timestamp) ! $birthday) { die(日期不存在); }这个二次校验技巧利用了date和strtotime的可逆性合法日期格式化后与原字符串完全一致非法日期如 2 月 30 日会被进位修正比较后即可发现不一致。PHP 7.4 到 8.3 版本下这段逻辑都可以稳定工作不需要针对版本做分支处理。时区设置方面PHP 8 中date_default_timezone_set(Asia/Shanghai)仍是推荐的初始化方式应放在应用入口文件最顶部。配置文件php.ini中的date.timezone也可以在服务器层面统一指定但入口函数设置优先级更高适合虚拟主机环境下无法修改php.ini的场景。另外要注意服务器系统时区和 PHP 时区可能不一致使用date(I)可以检测当前是否为夏令时但对于中国时区没有实际意义统一设置为Asia/Shanghai即可。6. 缓存与性能优化从单表查询到内存级响应6.1 Redis 缓存运势数据的键设计与过期策略星座运势属于低频更新、高频读取的数据非常适合缓存。一天的运势数据在当天内不会变化缓存命中率理论上接近 100%。使用 Redis 时键设计要同时包含星座、日期类型和日期避免不同数据互相覆盖?php function getDailyFortuneCached(PDO $pdo, Redis $redis, string $zodiacName): array { $today date(Y-m-d); $cacheKey zodiac:fortune:daily:{$zodiacName}:{$today}; $cached $redis-get($cacheKey); if ($cached ! false) { return json_decode($cached, true); } $fortune getDailyFortune($pdo, $zodiacName, $today); $expireAt strtotime($today . 23:59:59) - time(); $redis-setex($cacheKey, $expireAt, json_encode($fortune, JSON_UNESCAPED_UNICODE)); return $fortune; }setex设置过期时间为当天结束前的剩余秒数这样每天零点缓存自动失效新一天的运势数据自然生效无需手动清理。json_encode第三个参数JSON_UNESCAPED_UNICODE很关键如果不加中文运势文本会被转义成\uXXXX形式虽然 JSON 解析后内容不变但占用更多内存且可读性差。缓存穿透问题也值得留意如果数据库没有今天的运势数据缓存中不会写入任何内容每秒查询都会打到数据库。解决方案是缓存空值并设置较短的过期时间比如 5 分钟?php if (empty($fortune)) { $redis-setex($cacheKey, 300, json_encode([empty true])); return getDefaultFortune($zodiacName); }6.2 生日当天用户流量突增的应对思路星座运势站点有明显的流量波峰典型场景是某星座的生日月开始时该星座用户的访问量突然上升。数据库压力通常在缓存过期瞬间爆发。应对策略包括预热和错峰。预热即在每天零点前运行脚本将当天 12 个星座的运势数据提前写入缓存?php // prewarm.php 每天 23:50 执行 foreach ([白羊座,金牛座,双子座,巨蟹座,狮子座,处女座,天秤座,天蝎座,射手座,魔羯座,水瓶座,双鱼座] as $zodiac) { $fortune getDailyFortune($pdo, $zodiac, date(Y-m-d)); $cacheKey zodiac:fortune:daily:{$zodiac}: . date(Y-m-d); $redis-setex($cacheKey, 86400, json_encode($fortune, JSON_UNESCAPED_UNICODE)); }预热脚本在cron中设置为每天 23 点 50 分执行此时北京时间接近午夜执行耗时不敏感。86400秒过期时间与自然日对齐略大于当天剩余秒数确保次日 23:50 前缓存有效同时让预热脚本只负责写入新数据。6.3 静态页面生成与 Nginx FastCGI 缓存二选一当流量规模继续增长Redis 缓存仍需要 PHP-FPM 进程参与处理每个请求至少执行一次Redis get操作。进一步优化可以完全绕过 PHP 动态执行将星座运势页面生成静态 HTML 文件。但静态化的缺点是运势本身就是动态内容每天更新意味着每天要重新生成全部文件。一个折中方案是使用 PHP 内置的output buffer配合文件写入?php ob_start(); // 渲染运势页面的模板代码 $html ob_get_clean(); $filePath __DIR__ . /cache/zodiac_ . $zodiacName . _ . date(Ymd) . .html; if (file_put_contents($filePath, $html) ! false) { // 写入成功 }静态文件生成后Nginx 可以直接通过try_files优先查找对应的 HTML 文件未命中才转发给 PHP-FPM。改动地方是 Nginx 配置中的location /块增加一行静态文件检查逻辑。该方案适合日访问量在十万级到百万级的场景超过后需要引入 CDN 将静态文件分发到边缘节点。部署时要注意生成目录的写权限必须仅授予 PHP-FPM 运行用户避免其他进程误写导致权限混乱。反向代理缓存FastCGI Cache是另一个方向Nginx 直接缓存 PHP 响应适合不用修改业务代码的场景。启用方式是在 Nginxhttp或server块中配置缓存路径和过期时间然后注意事项是关键设置缓存键要包含请求参数因为不同星座对应的 URI 可能相同POST 请求不会被缓存。GET 请求按星座名设计 URL 路径时缓存键需要把$request_uri加入避免缓存串号。实际项目中我会优先用 Redis 缓存代码可控性更强而且可以复用连接池。FastCGI Cache配置示例fastcgi_cache_path /var/cache/nginx/fcgi levels1:2 keys_zonezodiac_cache:10m inactive1h; server { location ~ \.php$ { set $skip_cache 0; if ($request_method POST) { set $skip_cache 1; } if ($query_string ! ) { set $skip_cache 1; } fastcgi_cache_key $scheme$request_method$host$request_uri; fastcgi_cache_use_stale error timeout invalid_header http_500; fastcgi_cache_valid 200 60m; fastcgi_cache_bypass $skip_cache; fastcgi_no_cache $skip_cache; include fastcgi_params; fastcgi_pass unix:/var/run/php/php8.3-fpm.sock; } }fastcgi_cache_valid 200 60m表示仅缓存状态码为 200 的响应 60 分钟超时后自动回源重新请求动态接口。$query_string ! 跳过带查询参数的请求因为星座运势页面通常通过 URL 路径识别星座如/zodiac/aries如果使用?zodiacaries这种格式需要自定义缓存键。set $skip_cache 1的 if 语法是 Nginx 内嵌语法虽然官方不推荐使用if但在这个场景下配合set变量是兼容性最好的写法没有后续易于误判的问题。本文还有配套的精品资源点击获取
返回列表