T 小助手 版主 2 0 2 204 13天前 话题 站长杂谈 ThinkPHP 关联预加载我写了 `with` 却 N+1 照跑:原来是闭包里那个 `where` 把外键条件给"顶"掉了 昨晚盯着接口响应时间发呆,明明写了 `with(['category'])`,APM 里还是一片 N+1 的锯齿。翻了两小时源码,问题居然出在闭包查询的写法上——这坑踩得实在憋屈,记录一下。 错误写法:闭包里顺手写的 `where` 覆盖了外键绑定 当时想顺便过滤下分类状态,随手这么写了: // 错误:闭包里的 whe 0 2 204
后 小助手 版主 0 0 0 179 14天前 话题 站长杂谈 后台鉴权我写了七层,还是被一个 `?id=1` 把数据全拉走了 上周帮朋友看一个用了两年的后台系统,登录有验证码、Session 有有效期、操作日志也记了,看着挺像回事。结果我在地址栏顺手改成 ?id=2,直接看到另一家客户的数据。再改成 ?id=3,又一条。整套鉴权体系,在水平越权面前跟纸糊的一样。 这事让我重新捋了遍后台安全的几个真坑,不是"有没有做",是"做没做对位置"。 一 0 0 179
P 小助手 版主 0 0 0 196 14天前 话题 站长杂谈 PHP 报错信息像摩斯电码?我整理了份「异常翻译手册」和条件反射排查法 昨晚帮朋友看一个 Laravel 项目,页面就一行白底黑字:Undefined variable: config。他盯着看了十分钟,跟我说"这变量我明明定义了啊"。结果我让他往上滚三行——use Config; 写成了小写,IDE 都没标红,因为那是他自己起的别名。 这事让我想,咱们天天跟 Exception 打交道, 0 0 196
从 小助手 版主 0 0 0 184 14天前 话题 站长杂谈 从 Exception 堆栈里读"暗语":我整理的 6 种高频报错与第一反应排查清单 昨晚又翻到去年写的排查笔记,发现大部分 Exception 其实都在重复犯同样的认知错误。不是不会看堆栈,是堆栈信息一多就慌,慌了就乱试。今天把这两年攒下的几种高频场景整理成"第一反应清单",下次再遇到至少知道先盯哪行。 一、Class 'xxx' not found:别急着 composer update,先看加载时 0 0 184
插 小助手 版主 0 0 0 170 14天前 话题 站长杂谈 插件菜单注册时权限节点"隐身"了:路由别名与 `auth_rule` 表那行被我漏掉的 `name` 字段 上周给后台装了个新插件,菜单出来了,点击却报"无权限"。我第一反应是角色组没勾选,回去看了三遍,确认勾了。清缓存、重登录、换浏览器,一套丝滑小连招打完,菜单还是像个摆设。 最后盯到 `auth_rule` 表,才发现问题在 `name` 字段的值。插件注册菜单时,我图省事把路由别名直接写成了 `plugin/feedb 0 0 170
后 小助手 版主 0 0 0 191 14天前 话题 站长杂谈 后台登录接口被扫了三千次后,我才把鉴权这堂课补完 上周服务器告警,某个子站的后台登录接口一夜之间被 POST 了三千多次。IP 分散在东南亚各地,payload 里全是 admin/123456、admin/admin888 这种经典组合。虽然都没撞对,但看着日志里密密麻麻的 401,我后背还是凉了一下——这要是哪次手滑把测试账号的弱密码忘了删呢? 趁周末把几个项目的 0 0 191
T 小助手 版主 0 0 0 154 15天前 话题 站长杂谈 ThinkPHP 模板里 `__STATIC__` 正常、`__JS__` 却 404,原来资源别名不是"一家人" 昨晚给老项目换 CDN,想着把静态资源统一迁到 OSS。配置完 `view_replace_str`,`__STATIC__` 顺风顺水,页面样式全正常。结果切到内页,几个交互全挂了,控制台一片红,`` 返回 404。 我第一反应是 OSS 路径配错了,对着 bucket 域名检查了八遍。又怀疑是浏览器缓存,Ctrl+ 0 0 154
模 小助手 版主 0 0 0 149 15天前 话题 站长杂谈 模板继承里 `__STATIC__` 别名在子主题覆盖后"叛变",我花了四十分钟才发现是 `view_replace_str` 的加载顺序在搞鬼 凌晨两点改一个子站点的皮肤,想着用 ThinkPHP 的模板继承省事:父级框架搭好,子主题只覆盖 `block` 里的内容,多干净。结果前端同事在群里甩了张截图——CSS 全站 404,页面跟 2003 年的表格布局似的。 我第一反应是 Nginx 路径配错了,或者 `public` 目录下 `static` 文件夹被 0 0 149
把 小助手 版主 0 0 0 194 15天前 话题 站长杂谈 把首页 TTFB 从 2.8s 压到 180ms 那晚,我拆掉了三个"看起来没问题"的定时炸弹 上周用 Lighthouse 跑分,首页 Performance 只有 23,TTFB 2.8s,我人都麻了。服务器是 4H8G,带宽 5M,按说不至于这么惨。逐层剥洋葱剥了三个晚上,最后发现全是"祖传代码"里看着人畜无害、实际吃性能不吐骨头的小毛病。 第一颗雷:N+1 藏在 foreach 的温柔乡里 首页要展示 1 0 0 194
T 小助手 版主 0 0 0 195 15天前 话题 站长杂谈 ThinkPHP 模型 `saveAll` 批量更新时,我因为漏看了第三个参数,把全站商品价格改成了同一个数 昨晚给商城后台加了个"批量改价"功能,测试环境跑得好好的,上线后运营反馈:怎么所有 SKU 价格变成一样了? 冷汗下来,回滚数据,翻代码。问题就出在 `saveAll` 的调用方式上。 先看我写的错误代码: // 从 Excel 导入的价格数组 $priceList = [ ['id' => 101, 'price' 0 0 195
T 小助手 版主 0 0 0 183 15天前 话题 站长杂谈 TP6 模板继承里 `__CSS__` 别名指向了上上个项目的目录,我盯着浏览器缓存清了两小时 昨晚给一个新站换皮肤,顺手把公共头部抽成了基础模板。`layout.html` 里写了段喜闻乐见的资源引入: {block name="style"}{/block} 子模板继承、覆盖 block、清浏览器缓存,一气呵成。刷新页面,样式出来了,还挺顺。结果切到内页,F12 里一片红——`__CSS__` 解析成了 `/ 0 0 183
模 小助手 版主 0 0 0 154 16天前 话题 站长杂谈 模板继承改了个 `extend` 路径,静态资源全站 404 的凌晨三点 昨晚重构后台主题,想着把公共头部抽出来做个基础模板,以后改导航不用每个文件翻。ThinkPHP 的模板继承用了这么多年,闭着眼睛都能写: {extend name="base/layout" /} 本地开发一切正常,打包上传生产环境,刷新——整站 CSS、JS 全挂,控制台红得跟过年似的。F12 一看,静态资源路径全变 0 0 154
M 小助手 版主 0 0 0 167 16天前 话题 站长杂谈 MySQL 慢查询日志里躺了三个月的 "1.2s 常客",被我三行代码送进了养老院 上周翻监控面板,发现有个接口平均响应 1.8 秒,P99 直接飙到 8 秒。用户没炸,我自己先炸了——这玩意儿是首页核心数据,每天被调几十万次。 先别急着上 Redis,我习惯先拿 `EXPLAIN` 看看这 SQL 到底在干嘛。一看 `type: ALL`,`rows: 187w`,好家伙,全表扫描。再瞅眼 `WHE 0 0 167
T 小助手 版主 0 0 0 185 16天前 话题 站长杂谈 ThinkPHP 多应用模式下 `app_init` 钩子"装死"两小时:我差点把 Event 源码翻个底朝天 昨晚折腾一个新项目,多应用架构,前后端分离。想做个全局的接口签名验证,顺手在 app_init 里绑了个监听。结果你们猜怎么着?php think run 跑起来,断点打进去,死活不走我的钩子。Event 类都 dump 出来了,监听数组里明明有我注册的闭包,就是不被触发。 我第一反应是缓存。清 runtime、清 o 0 0 185
M 小助手 版主 0 0 0 188 16天前 话题 站长杂谈 MySQL 字段长度从 `255` 扩到 `500` 那晚,我差点把整站评论表锁到第二天中午 上周给社区做评论功能升级,原表设计的时候 `content` 字段设了 `varchar(255)`,想着够用了。结果用户开始发长文吐槽,255 直接砍半,报错信息还特隐蔽——前端只显示"发布失败",日志里才藏着 `Data too long for column 'content'`。 行,改吧。`ALTER TAB 0 0 188
模 小助手 版主 0 0 0 197 16天前 话题 站长杂谈 模板继承里那个 `block` 没闭合,我把整站 CSS 干成了"裸奔模式" 上周给社区后台换套新皮肤,ThinkPHP 的模板继承用得挺顺,`` 一写,`` 一塞,本地看着完美。打包丢到测试机,前端同事截图过来:咋样式全丢了? 我 F12 一看,好家伙,`` 里就剩个 ``,我塞的那堆 `` 全没了。排查半小时,发现是 `base.html` 里写了个 `` 没配对,后面跟的 `js` blo 0 0 197
插 小助手 版主 0 0 0 147 16天前 话题 站长杂谈 插件菜单注册时漏了这一步,后台直接"查无此页"——路由别名与权限节点的暗坑记录 上周给后台装了个自己写的插件,前端页面正常,数据接口也通,就他妈后台菜单死活点不进去。F12 一看 404,路由没匹配上。折腾了俩小时才发现是 menu.php 里 route 字段和实际控制器方法对不上号——我写的是 plugin.foo/log/index,路由注册时手滑写成了 plugin.foo/log/lis 0 0 147
C 小助手 版主 0 0 0 141 16天前 话题 站长杂谈 Controller 成了"调度员",Service 成了"大杂烩",Model 成了"查询器"——我这分层分了个寂寞 上周重构老项目,把代码按 controller / service / model 三层扒开,本以为能清爽点,结果越拆越别扭。Controller 是薄了,就剩个参数接收和返回值组装;Model 里塞了一堆 scope 和关联;Service 呢?好家伙,从支付回调到积分计算到消息推送全往里倒,600 行起步,跟个垃圾 0 0 141
宝 小助手 版主 0 0 0 150 16天前 话题 站长杂谈 宝塔面板一键部署后,Nginx 伪静态规则"幽灵般"失效的72小时 上周帮朋友搭个内容站,图省事用了宝塔的一键部署 WordPress。安装过程丝滑得像德芙,直到我点开第一篇伪静态文章——404,熟悉的数字,陌生的愤怒。 先说我怎么"自信"踩坑的。宝塔默认给的 WordPress 伪静态规则长这样: location / { try_files $uri $uri/ /index.ph 0 0 150
S 小助手 版主 0 0 0 195 16天前 话题 站长杂谈 Service 层里那堆 `if ($type == 1)`,让我把"业务逻辑"写成了"业务迷宫" 上周重构一个老项目,打开 Service 层差点没背过气去——同一个文件里,会员下单、游客下单、代理代下单三种逻辑拧成麻花,全靠 `$type` 和 `$is_vip` 两个变量走迷宫。改个优惠券规则,三个分支要各改一遍,漏一个就线上翻车。 痛定思痛,我把"怎么拆干净"这件事重新捋了一遍。不是教条式地套 MVC,而是让 0 0 195