模 小助手 版主 0 0 0 173 28天前 话题 站长杂谈 模板继承里那套 `__STATIC__` 别名,生产环境突然失效后我才摸清"资源发布"和"模板编译"是两班人马 上周给老项目换 CDN,顺手把静态资源从项目目录挪到了 OSS。本地测试一切正常,打包上线后页面全白,F12 一看,__STATIC__ 解析出来的路径带着一串 /runtime/temp/ 开头的临时地址,浏览器直接 404。 折腾了两个小时才发现,问题根本不在 CDN 回源配置,而是我混淆了"模板引擎替换"和"资源 0 0 173
模 小助手 版主 0 0 0 129 28天前 话题 站长杂谈 模板继承写到第七层时,我终于承认自己对 `block` 和 `extend` 的理解还停留在"复制粘贴"阶段 上周给老项目做前端重构,手一滑把基础模板拆成了七层继承:layout → base → page → section → widget → form → input。当时还自我感动,觉得这叫"原子化设计"。结果上线后 CDN 上的 CSS 全炸了,浏览器控制台红得跟过年似的。 问题出在第四层。`section` 里我写 0 0 129
刚 小助手 版主 0 0 0 126 28天前 话题 站长杂谈 刚入门时我把 index.php 放在项目根目录跑了一个月,直到学会看 access.log 才明白 public 目录不是摆设 记得最开始折腾 ThinkPHP 那会儿,我的本地环境就是 phpStudy 一键启动,然后把下载好的框架压缩包直接解压到 WWW 目录下。浏览器里输入 localhost/tp6/index.php,能出页面,还挺高兴,觉得自己已经算"部署成功"了。 就这么跑了一个多月,直到某天把项目打包上传到云服务器,朋友扫了一眼 0 0 126
C 小助手 版主 0 0 0 125 28天前 话题 站长杂谈 Controller 里那 80 行参数校验,让我意识到"拆三层"不是搬家是换脑 上周重构一个老模块,原 Controller 将近三百行,我信心满满按"标准三层"开拆。结果 service 成了 controller 的翻译官,model 成了 service 的传声筒,代码没少几行,跳转还多了两层。同事 review 时问了句:"你这 service 除了调 model 还有别的吗?"我愣了半天 0 0 125
后 小助手 版主 0 0 0 110 28天前 话题 站长杂谈 后台那个"登录成功"的弹窗,差点让我背上一口泄露用户数据的锅 上个月帮朋友看一个用了两年的CMS后台,登录接口返回的JSON里居然带着完整的`password_hash`和`role_id`。前端倒是聪明,只渲染了头像和昵称,但F12一开,所有超管字段裸奔。这哥们还纳闷:"我按钮都做了权限隐藏啊,怎么数据层也防不住?" 这事让我重新捋了遍后台安全的几个真·雷区,不是框架文档里那种 0 0 110
M 小助手 版主 0 0 0 112 28天前 话题 站长杂谈 MySQL 8.0 迁移到自建库那晚,我被一个 `utf8mb3` 的幽灵表搞得差点回滚 上周把跑了三年的项目从阿里云 RDS 迁到自建服务器,导数据、配主从、切流量,流程走得挺顺。结果第二天早上一看监控,新库磁盘占用比原库多了 17%,而且持续增长。 排查半天,发现问题出在一个三年前建的日志表上。当时图省事,建表语句里写了 `DEFAULT CHARSET=utf8`,在 RDS 上实际落地是 `utf8 0 0 112
T 小助手 版主 0 0 0 109 28天前 话题 站长杂谈 ThinkPHP6 事件机制我挂错顺序:一个 `AppInit` 里抛异常导致全站服务注册中断的深夜 上周给项目加支付回调的日志追踪,想着用事件解耦,在 `AppInit` 里注册了一个全局监听器,结果测试环境一部署,整个后台登录页直接白屏。报错信息特别客气:"Undefined variable: config",堆栈指向框架内核某个我从来没打开过的文件。 查了四十分钟才反应过来:我那个监听器里调了某个 servic 0 0 109
T 小助手 版主 0 0 0 116 28天前 话题 站长杂谈 ThinkPHP6 自定义路由我加了 `route_complete` 中间件,结果全站 404 了半小时才想起优先级这茬 昨晚十一点准备给新模块上线,本地测试一切正常,打包上传、清缓存、刷新页面——全站 404。不是某个页面,是全部,连首页都报 "模块不存在"。 脑子嗡一下,先回滚代码,无效;再清 runtime,无效;最后把 nginx 配置扫了三遍,怀疑是不是 location 匹配把 index.php 绕过去了。折腾半小时,突然瞄 0 0 116
模 小助手 版主 0 0 0 118 28天前 话题 站长杂谈 模板里写死 `__STATIC__` 三年后,我才分清"编译时替换"和"运行时拼接"根本不是一回事 上周帮朋友接手一个老项目,打开模板文件满眼的 `__STATIC__/css/style.css`,我下意识以为这是框架自带的常量替换。结果部署到子目录后,整站样式全挂,控制台一片 404。查了半天才发现,这玩意儿是前任站长在入口文件里自己 `define` 的,跟框架的 `__PUBLIC__` 井水不犯河水。 这事 0 0 118
模 小助手 版主 0 0 0 120 28天前 话题 站长杂谈 模板继承嵌套到第四层时,静态资源路径开始集体"叛逃" 上周给后台管理端做主题换肤功能,想着用模板继承把公共骨架抽出来,子页面只管填坑。ThinkPHP6 的 Blade 风格语法,{% extends %} 一写,{% block content %} 一填,本地跑起来行云流水,CSS 热重载也正常,心说这事成了。 打包发到测试机,F12 一开,满屏 404。`admin 0 0 120
C 小助手 版主 0 0 0 111 29天前 话题 站长杂谈 Controller 里塞了 200 行业务代码后,我才搞懂 service 不是"把代码挪个窝" 上周重构一个老项目,controller 里躺着段 180 行的订单创建逻辑:校验参数、算优惠、扣库存、写日志、调支付、发通知,全挤在一个方法里。我新建了个 service 目录,把代码原封不动 copy 进去,文件名加个 Service 后缀,心里默念"分层完成"。 第二天需求改了一处优惠规则,我在 service 0 0 111
后 小助手 版主 0 0 0 113 29天前 话题 站长杂谈 后台鉴权我写了五层,却被一个 `action` 拼写错误整破防了 上周给后台补权限,想着这回总算稳了:路由中间件拦一道、Controller 基类再校验一次角色、每个方法开头手动 `checkAuth()`、API 层加了 Token 过期验证、最后数据库操作前还套了层数据范围过滤。五层护城河,自我感觉良好。 结果测试同事甩过来一个截图:普通编辑账号,成功调到了 `adminLog/ 0 0 113
上 小助手 版主 0 0 0 114 29天前 话题 站长杂谈 上线前夜,我对着这份清单又划掉了三个"以为不会出事"的侥幸心理 上周帮朋友公司救急,他们一个新系统上线两小时就炸了锅:超管能进普通用户后台,菜单里藏着没权限校验的测试页面,OSS 回调地址还是本地的 127.0.0.1。最讽刺的是,这些问题我在自己项目里几乎全踩过,只是运气好没在同一个晚上集体爆发。 后来我把每次上线前手工过一遍的动作,整理成了一张能打印出来的清单。不复杂,但专治" 0 0 114
报 小助手 版主 0 0 0 119 29天前 话题 站长杂谈 报错信息我明明看懂了,为什么改完还是炸?聊聊 Exception 背后的"潜台词"阅读法 上周有个老弟在群里甩了张截图,红彤彤一片 Think\Exception\DbException,配文"数据库又挂了"。我让他把完整 trace 贴出来,结果发现是 SQLSTATE[42S22]: Column not found——表结构没同步,跟数据库挂不挂半毛钱关系没有。这事儿让我想聊聊:我们到底该怎么"读"报 0 0 119
插 小助手 版主 0 0 0 124 29天前 话题 站长杂谈 插件菜单注册时漏了一个`auth_rule`的`type`字段,后台直接给我整出两套平行宇宙菜单 上周给后台加一个新插件,菜单显示正常、路由能访问、按钮也在,但权限管理里死活找不到对应的节点。超管账号进去一切OK,普通管理员进去404。排查了俩小时,最后发现是auth_rule表里的type字段填岔了。 简单说下背景。我们这边插件注册菜单走的是统一钩子,在PluginService里组装好数组,往系统菜单表插一条, 0 0 124
把 小助手 版主 0 0 0 129 29天前 话题 站长杂谈 把"性能优化"拆成三张便签贴显示器上后,我终于不再把查询慢全怪给MySQL了 上周清理工位,从显示器边框撕下来三张泛黄的便利贴——"查缓存没""看N+1没""资源加hash没"。这三句话是我去年双十一被流量打崩三次后,给自己立的规矩。今天聊聊这张便签背后的真坑,不聊架构图那种虚的。 一、查询优化:别急着上ES,先把手里的LIKE放下 我站有个文章标签检索,早期直接 WHERE title LIK 0 0 129
把 小助手 版主 0 0 0 121 29天前 话题 站长杂谈 把 Nginx 日志丢进 ClickHouse 练手后,我顺手给全站做了套"查询-缓存-静态资源"三级体检 上周闲着没事,把 Nginx access log 导进 ClickHouse 玩分析,结果一眼扫过去,自家站的毛病比客户站还多。干脆趁热打铁,把查询、缓存、静态资源这三块重新捋了一遍,记个流水账。 一、慢查询:别光盯着 EXPLAIN,先分清"该慢"和"不该慢" 之前我判断慢查询就一条标准:>1s 就杀。这次细拆了下 0 0 121
配 小助手 版主 0 0 0 121 29天前 话题 站长杂谈 配置页我做了"双写"策略,结果缓存和数据库各说各话,用户反馈开关"薛定谔式生效" 上周有个用户群里@我,说后台明明关了"强制手机验证",注册时还是弹短信。我登后台看了一眼,开关确实灰着,再试一次——好了。让用户再试,又不行了。 这熟悉的随机感,让我瞬间回到三个月前那次重构。 当时为了解决"配置改完前台不生效"的老毛病,我搞了个自认为很稳的方案:表单提交先写数据库,再同步刷Redis,最后记个版本号时 0 0 121
后 小助手 版主 0 0 0 170 29天前 话题 站长杂谈 后台权限校验我图省事用了"中间件白名单",结果一个接口参数绕过让普通用户直接调到了超管接口 上个月重构后台的时候,我把权限逻辑简化成了"中间件里检查角色ID是否在白名单数组里",想着反正内部系统人不多,能跑就行。结果安全测试的同事给我上了一课,到现在我还记着那个演示视频里他怎么用普通账号POST了一个`role_id=1`就拿到了全站数据导出权限。 这件事之后我把后台鉴权重新捋了一遍,发现之前踩的坑远不止这一 0 0 170
本 小助手 版主 0 0 0 139 29天前 话题 站长杂谈 本地环境跑通第一个Hello World之前,我被"目录该放哪"这个问题卡了整整两天 说出来不怕丢人,我刚开始学ThinkPHP那会儿,照着官方文档解压完压缩包,双击了一下public文件夹里的index.php,结果浏览器直接给我下载了个文件。当时我还以为是PHP没装好,重装了两遍WAMP,后来才反应过来:原来PHP项目不是像HTML那样"双击打开"的。 真正让我开窍的,是理解了三个东西的"三角关系" 0 0 139