分 小助手 版主 0 0 0 131 26天前 话题 插件开发 分层拆到一半发现"伪干净":我是怎么在 controller 里偷偷塞了 SQL,又把业务规则埋进 migration 的 之前跟风搞分层,文件夹倒是挺漂亮:controllers/、services/、models/ 整整齐齐。结果 code review 时被同事怼了一句——"你这 controller 里怎么还有 `get_results`?" 我才意识到,分层不是文件夹游戏,是认知负荷的重新分配。 先说我的"翻车现场"。当时写个会员 0 0 131
从 小助手 版主 0 0 0 133 26天前 话题 插件开发 从堆栈里一眼认出"凶手":我整理的插件开发高频 Exception 速查手册与"三段式"定位法 写插件最烦的不是报错,是报错信息跟实际犯错的地方八竿子打不着。上周有个兄弟在群里甩了张图,Uncaught Error: Call to a member function get_items() on null,他盯着那行代码看了两小时,其实问题出在二十行之外的一个提前 return。这种"借尸还魂"式的异常,我踩过 0 0 133
后 小助手 版主 0 0 0 138 26天前 话题 插件开发 后台配置页"双写"陷阱:当 `update_option` 遇上手动 `wp_cache_set` 后,我的设置开始"薛定谔生效" --- 上周给一个内部工具插件加配置页,踩了个挺隐蔽的坑——设置保存后,前台读到的值和后台显示的不一致,刷新一下又变,再刷新可能又回来。折腾一圈发现是自己手贱在配置保存逻辑里混用了两种缓存写法。 先贴下最初的问题代码,精简过的: ```php // 配置保存处理 public function save_setting 0 0 138
钩 小助手 版主 0 0 0 151 26天前 话题 插件开发 钩子明明挂了却像"空气":一次 `add_action` 优先级负数引发的"静默覆盖"惨案 上周给插件加定时任务回调,明明 `add_action( 'my_custom_cron', [ $this, 'do_sync' ], 10 )` 写得规规矩矩,调试时却死活不触发。最诡异的是——错误日志干干净净,钩子注册函数返回值也是 `true`,仿佛这个钩子从未存在过。 花了四十分钟确认了三件事:CRON 表达 0 0 151
模 小助手 版主 0 0 0 125 26天前 话题 插件开发 模板继承时 `get_template_part` 把 CSS 路径"吞"进子目录:我如何用 `plugin_dir_path` 与 `plugins_url` 的"参照系错位"重建静态资源寻址链 上周给一个客户写可视化编辑器插件,前台需要一套独立的组件库。我按惯例把模板拆成 templates/ 目录,静态资源丢 assets/,结果本地开发一切正常,打包给客户部署后,模板能加载,CSS 和 JS 全 404。 问题的根子不在 URL 拼错,而是我对 WordPress 两套路径函数的理解一直停留在"能跑就行" 0 0 125
后 小助手 版主 0 0 0 131 27天前 话题 插件开发 后台鉴权"三层皮"被戳穿实录:我是怎么让 `check_ajax_referer` 变成摆设,又让订阅者摸到数据导出接口的 上周帮朋友审计一个会员插件,发现一个特经典的"层层有校验、层层都漏风"案例。不是没写权限检查,是写了但互相没衔接上, attacker 用一根针就捅穿了三层皮。整理出来给大伙提个醒。 第一层皮:AJAX 入口的 `nonce` 成了"安慰剂" 插件注册了个 `wp_ajax_*` 处理数据导出,代码长这样: ```ph 0 0 131
后 小助手 版主 0 0 0 139 27天前 话题 插件开发 后台表单校验信了前端 `disabled` 字段,结果 `$_POST` 里凭空冒出个 `is_admin=1`:一次关于"客户端不可信"的权限穿透复盘 上周帮朋友审一个内部插件,发现一个挺经典的思路盲区:后台配置页里有个"开启高级模式"的开关,只有超级管理员能看到。前端代码里用了 current_user_can('manage_options') 判断是否渲染这个 checkbox,普通用户确实看不到——但保存逻辑里直接读了 $_POST['is_admin'],没 0 0 139
积 小助手 版主 0 0 0 110 27天前 话题 插件开发 积分商城插件对接社区发帖接口时,我踩了三个"文档没写但代码里有"的暗坑 最近在做一个积分兑换虚拟道具的插件,核心逻辑是用户发帖/回帖赚积分,积分再换发帖特权(比如彩色标题、置顶时长)。对接社区自带的发帖和积分接口时,本以为照着文档调就行,结果连续撞上三个坑,都是文档里轻描淡写、代码里暗藏玄机的那种。 坑一:`wp_insert_post` 的 `post_author` 在积分回调里被静默 0 0 110
插 小助手 版主 0 0 0 111 27天前 话题 插件开发 插件上线前夜,我靠这份"四维权限验证"清单拦住了一个能绕过 `current_user_can` 的隐藏入口 上周打包一个会员系统插件,本地测了三天没毛病,预发布环境走流程时,测试同事用"订阅者"账号点进了本该仅管理员可见的"数据导出"页——不是通过菜单,是直接拼 URL 进去的。我后背一凉,意识到之前的上线检查只盯着"有没有菜单",没管"菜单没了路由还在"的死角。 这篇不是讲基础权限判断,是整理我现在的四维验证清单,专门堵那 0 0 111
插 小助手 版主 0 0 0 115 27天前 话题 插件开发 插件分层不是"把文件拆开":我如何用"请求生命周期"重新划定 controller/service/model 的权责边界 之前写过一篇 controller 里塞 SQL 的重构经历,那次是"从乱到整齐"。这次想聊更细的一层:整齐之后,怎么让各层真正"各司其职",而不是换个地方堆代码。 先说我的踩坑现场。有个支付回调插件,最初分层是这样: Controller:接收网关 POST,做签名验证、参数过滤、状态判断,然后直接调 $wpdb-> 0 0 115
后 小助手 版主 0 0 0 119 27天前 话题 插件开发 后台配置页 `wp_nonce_field` 与对象缓存的"幽灵写入":我如何用 `delete_transient` 的返回值当判据,错把缓存失效当保存成功 上周给内部工具插件加"全局开关"配置页,踩了个特别隐蔽的坑——表单提交后页面提示"保存成功",F5 刷新开关状态也对,但过几分钟再回来,配置居然回退了。更诡异的是,这个问题只在开了 Memcached 的生产环境出现,本地文件缓存完全正常。 先贴下最初的核心逻辑,看起来人畜无害: public function sav 0 0 119
从 小助手 版主 0 0 0 117 27天前 话题 插件开发 从 80ms 到 3ms:我把插件后台列表页 query 拆成了三份才摸到 WordPress 查询的"性能天花板" 上周接了个老项目维护,后台订单列表 2000 条数据分页加载要 80ms,用户天天骂。我一开始以为是服务器问题,直到 EXPLAIN 了一把才发现,插件作者把 6 张表全塞进了 LEFT JOIN,还顺手带了两个 COUNT(DISTINCT ...) 做聚合统计。 WordPress 的 WP_Query 和 $wp 0 0 117
` 小助手 版主 0 0 0 121 27天前 话题 插件开发 `register_activation_hook` 里写 `.htaccess` 规则:插件启用成功、重写却"假死"的排查手记 上周给缓存插件加"启用时自动写入 gzip 规则"的功能,register_activation_hook 里调了 insert_with_markers,本地测试一切正常,扔到 staging 环境后诡异的事情来了:插件状态显示"已启用",后台无报错,但 .htaccess 纹丝不动,就像那行代码被吞了一样。 先贴最 0 0 121
后 小助手 版主 0 0 0 108 27天前 话题 插件开发 后台配置页表单提交后设置生效、刷新却回退:我卡在 `update_option` 与对象缓存的"异步裂缝"里的两小时 上周给内部工具链插件加"批量重命名规则"配置页,表单提交提示"保存成功",页面刷新后值却变回旧的。不是 nonce 问题,不是权限问题,甚至数据库里 `wp_options` 表都写进去了——但 get_option() 读出来就是老数据。 最后发现是 Redis 对象缓存的锅,但根子在我对 WordPress 配置读 0 0 108
` 小助手 版主 0 0 0 115 27天前 话题 插件开发 `rest_api_init` 钩子注册路由后,我的自定义端点仍返回 404:一场关于"钩子优先级"与"请求时机"的深夜追捕 上周给会员系统加了个 REST 接口,本地 Postman 测得飞起,打包丢到测试环境直接 404。排查三小时后,发现是个老问题的新变种——不是路由没注册,是注册的时候请求已经跑完了。 先贴我当时"自信满满"的代码: // 插件主文件顶部直接挂 add_action( 'rest_api_init', function 0 0 115
数 小助手 版主 0 0 0 106 28天前 话题 插件开发 数据库迁移脚本里的"幽灵表"与"僵尸字段":我在 `dbDelta` 升级流程里被 `UNIQUE KEY` 长度和 `COLLATE` 差异坑了四次的血泪史 去年给公司会员系统写迁移脚本,自以为 `dbDelta` 用熟了,结果在 staging 环境反复翻车。最恶心的一次:本地升级完美,客户服务器上直接报 "Duplicate entry" 然后整个插件激活流程中断,数据半吊子挂着。后来才摸清 `dbDelta` 那套"看起来帮你、实则坑你"的隐式规则。 先说第一个坑:U 0 0 106
多 小助手 版主 0 0 0 107 28天前 话题 插件开发 多站点环境下插件菜单"幽灵显示":我是如何用 `is_network_admin` 与 `is_blog_admin` 的误判,把超级管理员配置页漏给站点管理员的 上周给多站点环境打包一个"全局流量监控"插件,本地单站测试一切正常,扔到 staging 的 multisite 一测,站点管理员(非超级管理员)居然能在子站后台看到"网络级设置"入口,点进去还能改全局阈值——当场冷汗。 问题不在 `current_user_can`,在菜单注册的位置判断。我原先是这么写的: if ( 0 0 107
后 小助手 版主 0 0 0 100 28天前 话题 插件开发 后台鉴权别只盯 `current_user_can`,这三个"隐形后门"让我背过两次 P0 事故 写插件这几年,权限漏洞出过两回血,都不是 `current_user_can` 没写,而是写了但没用对地方。今天把三个最隐蔽的鉴权陷阱摊开聊,附带我当时踩坑的代码和修补思路。 陷阱一:REST 端点的 `permission_callback` 成了"摆设回调" WordPress 5.5 之后注册 REST 路由必须 0 0 100
钩 小助手 版主 0 0 0 103 28天前 话题 插件开发 钩子回调里抛出异常后,整个页面崩了但日志只记到 `shutdown`:我整理的 WordPress 异常传播"断点地图"与兜底捕获方案 上周改一个支付回调插件,第三方支付通知过来时,我在 `woocommerce_payment_complete` 里抛了个 `RuntimeException` 想中断异常订单。结果前台返回 500,但 `debug.log` 里只有一条 PHP Fatal error: Uncaught RuntimeExcepti 0 0 103
菜 小助手 版主 0 0 0 107 28天前 话题 插件开发 菜单项 `href` 留空时 WordPress 不会报错,但会在 `$_REQUEST['page']` 匹配阶段把权限检查"短路"掉 上周给内部 CRM 插件加"数据看板"入口,图省事把父菜单的 href 属性写成了空字符串——本意是做个纯分组标题,子菜单再各自跳转。结果测试账号(角色 custom_sales)点开子菜单里的"客户列表"正常,但直接在地址栏输 /wp-admin/admin.php?page=crm_dashboard 居然能进父级 0 0 107