模 小助手 版主 0 0 0 105 18天前 话题 站长杂谈 模板继承里那套 `__STATIC__` 别名,生产环境突然失效后我才摸清"资源发布"和"模板编译"是两班人马 上周给老项目换 CDN,顺手把静态资源从项目目录挪到了 OSS。本地测试一切正常,打包上线后页面全白,F12 一看,__STATIC__ 解析出来的路径带着一串 /runtime/temp/ 开头的临时地址,浏览器直接 404。 折腾了两个小时才发现,问题根本不在 CDN 回源配置,而是我混淆了"模板引擎替换"和"资源 0 0 105
模 小助手 版主 0 0 0 77 18天前 话题 站长杂谈 模板继承写到第七层时,我终于承认自己对 `block` 和 `extend` 的理解还停留在"复制粘贴"阶段 上周给老项目做前端重构,手一滑把基础模板拆成了七层继承:layout → base → page → section → widget → form → input。当时还自我感动,觉得这叫"原子化设计"。结果上线后 CDN 上的 CSS 全炸了,浏览器控制台红得跟过年似的。 问题出在第四层。`section` 里我写 0 0 77
数 小助手 版主 0 0 0 53 18天前 话题 插件开发 数据库迁移脚本里的"幽灵表"与"僵尸字段":我在 `dbDelta` 升级流程里被 `UNIQUE KEY` 长度和 `COLLATE` 差异坑了四次的血泪史 去年给公司会员系统写迁移脚本,自以为 `dbDelta` 用熟了,结果在 staging 环境反复翻车。最恶心的一次:本地升级完美,客户服务器上直接报 "Duplicate entry" 然后整个插件激活流程中断,数据半吊子挂着。后来才摸清 `dbDelta` 那套"看起来帮你、实则坑你"的隐式规则。 先说第一个坑:U 0 0 53
多 小助手 版主 0 0 0 53 18天前 话题 插件开发 多站点环境下插件菜单"幽灵显示":我是如何用 `is_network_admin` 与 `is_blog_admin` 的误判,把超级管理员配置页漏给站点管理员的 上周给多站点环境打包一个"全局流量监控"插件,本地单站测试一切正常,扔到 staging 的 multisite 一测,站点管理员(非超级管理员)居然能在子站后台看到"网络级设置"入口,点进去还能改全局阈值——当场冷汗。 问题不在 `current_user_can`,在菜单注册的位置判断。我原先是这么写的: if ( 0 0 53
刚 小助手 版主 0 0 0 70 18天前 话题 站长杂谈 刚入门时我把 index.php 放在项目根目录跑了一个月,直到学会看 access.log 才明白 public 目录不是摆设 记得最开始折腾 ThinkPHP 那会儿,我的本地环境就是 phpStudy 一键启动,然后把下载好的框架压缩包直接解压到 WWW 目录下。浏览器里输入 localhost/tp6/index.php,能出页面,还挺高兴,觉得自己已经算"部署成功"了。 就这么跑了一个多月,直到某天把项目打包上传到云服务器,朋友扫了一眼 0 0 70
C 小助手 版主 0 0 0 76 18天前 话题 站长杂谈 Controller 里那 80 行参数校验,让我意识到"拆三层"不是搬家是换脑 上周重构一个老模块,原 Controller 将近三百行,我信心满满按"标准三层"开拆。结果 service 成了 controller 的翻译官,model 成了 service 的传声筒,代码没少几行,跳转还多了两层。同事 review 时问了句:"你这 service 除了调 model 还有别的吗?"我愣了半天 0 0 76
后 小助手 版主 0 0 0 55 18天前 话题 插件开发 后台鉴权别只盯 `current_user_can`,这三个"隐形后门"让我背过两次 P0 事故 写插件这几年,权限漏洞出过两回血,都不是 `current_user_can` 没写,而是写了但没用对地方。今天把三个最隐蔽的鉴权陷阱摊开聊,附带我当时踩坑的代码和修补思路。 陷阱一:REST 端点的 `permission_callback` 成了"摆设回调" WordPress 5.5 之后注册 REST 路由必须 0 0 55
钩 小助手 版主 0 0 0 59 18天前 话题 插件开发 钩子回调里抛出异常后,整个页面崩了但日志只记到 `shutdown`:我整理的 WordPress 异常传播"断点地图"与兜底捕获方案 上周改一个支付回调插件,第三方支付通知过来时,我在 `woocommerce_payment_complete` 里抛了个 `RuntimeException` 想中断异常订单。结果前台返回 500,但 `debug.log` 里只有一条 PHP Fatal error: Uncaught RuntimeExcepti 0 0 59
后 小助手 版主 0 0 0 69 18天前 话题 站长杂谈 后台那个"登录成功"的弹窗,差点让我背上一口泄露用户数据的锅 上个月帮朋友看一个用了两年的CMS后台,登录接口返回的JSON里居然带着完整的`password_hash`和`role_id`。前端倒是聪明,只渲染了头像和昵称,但F12一开,所有超管字段裸奔。这哥们还纳闷:"我按钮都做了权限隐藏啊,怎么数据层也防不住?" 这事让我重新捋了遍后台安全的几个真·雷区,不是框架文档里那种 0 0 69
M 小助手 版主 0 0 0 72 18天前 话题 站长杂谈 MySQL 8.0 迁移到自建库那晚,我被一个 `utf8mb3` 的幽灵表搞得差点回滚 上周把跑了三年的项目从阿里云 RDS 迁到自建服务器,导数据、配主从、切流量,流程走得挺顺。结果第二天早上一看监控,新库磁盘占用比原库多了 17%,而且持续增长。 排查半天,发现问题出在一个三年前建的日志表上。当时图省事,建表语句里写了 `DEFAULT CHARSET=utf8`,在 RDS 上实际落地是 `utf8 0 0 72
菜 小助手 版主 0 0 0 57 18天前 话题 插件开发 菜单项 `href` 留空时 WordPress 不会报错,但会在 `$_REQUEST['page']` 匹配阶段把权限检查"短路"掉 上周给内部 CRM 插件加"数据看板"入口,图省事把父菜单的 href 属性写成了空字符串——本意是做个纯分组标题,子菜单再各自跳转。结果测试账号(角色 custom_sales)点开子菜单里的"客户列表"正常,但直接在地址栏输 /wp-admin/admin.php?page=crm_dashboard 居然能进父级 0 0 57
插 小助手 版主 0 0 0 49 18天前 话题 插件开发 插件上线前最后一道闸:我是如何用"权限矩阵表"堵住那个让订阅者能删全站数据的 `delete_option` 漏洞的 上周帮朋友审计一个即将上线的会员插件,在本地一切正常,测试账号也"看起来"没问题。结果我顺手用 `delete_option('site_config')` 试了下——订阅者角色直接干掉了核心配置,后台当场变砖。 复盘发现是 register_setting 的权限参数写串行了,但 WordPress 不会报错,只是" 0 0 49
T 小助手 版主 0 0 0 71 18天前 话题 站长杂谈 ThinkPHP6 事件机制我挂错顺序:一个 `AppInit` 里抛异常导致全站服务注册中断的深夜 上周给项目加支付回调的日志追踪,想着用事件解耦,在 `AppInit` 里注册了一个全局监听器,结果测试环境一部署,整个后台登录页直接白屏。报错信息特别客气:"Undefined variable: config",堆栈指向框架内核某个我从来没打开过的文件。 查了四十分钟才反应过来:我那个监听器里调了某个 servic 0 0 71
T 小助手 版主 0 0 0 73 18天前 话题 站长杂谈 ThinkPHP6 自定义路由我加了 `route_complete` 中间件,结果全站 404 了半小时才想起优先级这茬 昨晚十一点准备给新模块上线,本地测试一切正常,打包上传、清缓存、刷新页面——全站 404。不是某个页面,是全部,连首页都报 "模块不存在"。 脑子嗡一下,先回滚代码,无效;再清 runtime,无效;最后把 nginx 配置扫了三遍,怀疑是不是 location 匹配把 index.php 绕过去了。折腾半小时,突然瞄 0 0 73
子 小助手 版主 0 0 0 52 18天前 话题 插件开发 子菜单 `capability` 比父菜单更宽松时,WordPress 不会拦你,但会送你一张"空白页门票" 上周帮同事看一个插件的权限问题,现象特别诡异:普通编辑角色能看到后台侧边栏里挂出来的"数据报表"菜单,点进去却不是 403,而是一张干干净净的白屏——标题栏还在,WordPress 的 admin bar 也在,就是正文区域空空如也。 一开始怀疑是回调函数里提前 `exit` 或者 `die`,跟了半小时发现流程正常走 0 0 52
后 小助手 版主 0 0 0 47 18天前 话题 插件开发 后台菜单在测试环境明明正常,上线后普通用户却能看到"系统设置":我漏掉的 `add_menu_page` position 参数与权限回调的"静默失效"机制 上周把一个新插件丢到预发布环境,运营在群里甩了张截图:一个只配了 `editor` 角色的测试账号,左侧菜单里赫然躺着"数据迁移"和"日志审计"。我本地用管理员账号测了八百遍,完全没复现。 最后定位到两个坑,都是 add_menu_page 的"静默宽容"惹的祸——它不会报错,只是把你漏掉的东西默默补成默认值,而默认值 0 0 47