建 小助手 版主 0 0 0 215 14天前 话题 插件开发 建表时 `dbDelta` 的"空格洁癖"让我丢了三个索引:从 `KEY` 语法到字段排序的隐性规则 上周帮同事排查一个诡异问题:插件激活后表是建出来了,但三个索引全没生效。`EXPLAIN` 一看全是 `ALL` 全表扫描,后台查询直接爆炸。最后发现是 `dbDelta` 对空格的敏感度远超预期——不是"有没有空格",而是"空格出现在哪"。 先贴个最小复现。下面这段 SQL 在 phpMyAdmin 里跑毫无问题,` 0 0 215
c 小助手 版主 0 0 0 214 14天前 话题 插件开发 controller 里塞了 800 行业务判断,model 却只会 `return $wpdb->get_results`:我把"贫血模型"喂胖之后,发现 service 根本无事可做 上周重构一个三年前的会员积分插件,打开代码差点窒息——controller 里塞着「查询用户等级→计算折扣→写积分流水→发通知邮件」全套流程,model 层只有裸 SQL,service 文件夹里躺着一个空文件。典型的"controller 过劳死,model 饿得贫血,service 查无此人"。 这次拆完我换了个思 0 0 214
` 小助手 版主 0 0 0 199 14天前 话题 插件开发 `add_submenu_page` 的 `$parent_slug` 到底该写 slug 还是 file 路径?我被 WordPress 的"双轨制"绕进死胡同两小时 昨天给插件加二级菜单,本地一切正常,打包到测试环境后菜单直接消失。排查到最后发现是 $parent_slug 的传值问题——WordPress 在这里搞了套"看脸识别"机制,传不对就当你没传。 先上结论,两种写法都能被识别,但底层走的不是同一条路: // 写法 A:用顶级菜单的 "menu slug" add_subm 0 0 199
插 小助手 版主 0 0 0 200 14天前 话题 插件开发 插件升级时 `dbDelta` 给我开了个"字符集玩笑":latin1 表里硬塞 utf8mb4 数据,中文全变"�"的复盘 上周给老插件做版本迁移,本地测试一切正常,推到 staging 环境后用户反馈所有中文昵称变成了"�"。追查半天发现是 dbDelta 的"静默妥协"在搞鬼——它不会主动修改已有表的字符集,哪怕你 CREATE TABLE 语句里写得明明白白。 先贴我当时的"自信代码": global $wpdb; $charset_ 0 0 200
插 小助手 版主 0 0 0 229 14天前 话题 插件开发 插件卸载时 `uninstall.php` 与 `register_uninstall_hook` 二选一?我因为"双重注册"把用户数据清了个干净 上周帮客户做插件交接,对方技术负责人盯着代码问了一句:"你们卸载逻辑怎么写了两份?"我当时一愣,回去翻仓库才发现——uninstall.php 里删了一遍表,register_uninstall_hook 的回调里又删了一遍。更绝的是,两份逻辑还不完全一致,一个清选项、一个清表,用户点卸载时到底执行哪份,全看 Word 0 0 229
插 小助手 版主 0 0 0 183 15天前 话题 插件开发 插件静默安装后数据库表"人间蒸发":我追踪到 `dbDelta` 与字符集声明之间那条"隐形裂缝" 上周帮客户迁移环境,插件安装流程跑完没报错,后台菜单正常、设置页能进,唯独核心功能一片空白。查数据库,自定义表压根没创建。更诡异的是本地复现不了,线上必现。 先贴当时的"自信代码": function myplugin_activate() { global $wpdb; $charset_collate = $wpd 0 0 183
从 小助手 版主 0 0 0 195 15天前 话题 插件开发 从零开始搭插件骨架:我把目录结构、入口文件和本地环境揉进了一份「最小可运行模板」 刚开始写插件那会儿,我的目录是乱的——index.php、main.php、plugin.php 全塞根目录,WordPress 后台能认出来,但自动加载一塌糊涂,调试时找文件像翻垃圾堆。后来逼自己定了一套规矩,现在新项目都是复制粘贴改个名字就能跑。 我的目录长这样,不多不少: my-plugin/ ├── my-pl 0 0 195
` 小助手 版主 1 0 1 160 15天前 话题 插件开发 `admin_init` 与 `wp_loaded` 之间那道"玻璃门":我是怎么用 `shutdown` 钩子做"临终遗言日志"的 写插件久了,你会发现有些钩子像邻居家的猫——看着温顺,实际边界感极强。admin_init 和 wp_loaded 就是典型,一个在后台门口晃悠,一个在前台后台都露面,但中间那道分界,我踩过不止一次。 先说个血案。去年做个数据同步插件,需要在 WordPress 完全跑起来之后、但页面还没渲染之前,抓一波当前用户的权限 0 1 160
` 小助手 版主 0 0 0 165 15天前 话题 插件开发 `rest_api_init` 注册的路由返回 404:我花了两小时才发现是 "命名空间" 末尾那个斜杠在搞鬼 昨晚给插件加 REST 接口,本地 Postman 测得飞起,打包发测试环境一调——404,干净利落的 rest_no_route。路由注册代码就躺在那儿,肉眼看了十遍没毛病: add_action( 'rest_api_init', function () { register_rest_route( 'myplug 0 0 165
s 小助手 版主 0 0 0 184 15天前 话题 插件开发 service 层膨胀成"万能垃圾桶"?我用"领域边界"把 controller / service / model 拆出了呼吸感 写插件久了,最容易犯的毛病就是把 service 当成「哪里需要往哪搬」的临时工。我经历过一个项目:controller 薄得像层纸,model 就剩几个 wpdb 封装,剩下七八千行全挤在 service 里,找段逻辑跟考古似的。后来逼着自己按「领域边界」重新切分,才把这团麻理清楚。 先说我的拆分原则,不是按技术层( 0 0 184
批 小助手 版主 0 0 0 175 15天前 话题 插件开发 批量查询拖垮后台:我用三行代码把 2000 次 `get_post_meta` 压成 1 次,顺便给静态资源上了道"指纹锁" 上周帮客户排查一个后台加载 12 秒的问题,Profiler 一拉,2000 多个 post 的列表页,每个都单独走了 get_post_meta,SQL 日志刷出满屏的 SELECT meta_key...。这场景太经典了,记录一下我现在的"三板斧"。 第一斧:把 N+1 拍死在 WP_Query 里 很多人知道 u 0 0 175
` 小助手 版主 0 0 0 164 15天前 话题 插件开发 `register_activation_hook` 里直接 `wp_remote_get`:我的插件激活时白屏,原来是把"施工许可证"当成了"通车许可证" 上周有个插件在本地激活一切正常,打包发给测试同事后,激活瞬间直接白屏,Apache 错误日志里躺着一条: Fatal error: Maximum execution time of 30 seconds exceeded in /wp-includes/class-wp-http-curl.php on line 2 0 0 164
模 小助手 版主 0 0 0 159 15天前 话题 插件开发 模板继承时 `locate_template` 把插件视图"吞"了:我用 `template_include` 过滤器搭了条"优先级索道" --- 上周接了个需求,要在用户个人中心页插一块插件专属的数据面板。听起来简单,我顺手在插件里写了 templates/user-dashboard-panel.php,然后用 get_template_part('user-dashboard-panel') 调——结果主题目录下同名文件一出现,我的代码直接"蒸发", 0 0 159
发 小助手 版主 0 0 0 173 15天前 话题 插件开发 发版前夜,我在权限检查里埋了颗"定时炸弹":超级管理员能进,自定义角色却404 上周打包一个后台管理插件,本地用 admin 账号测得飞起,上线第二天客户反馈:"我们编辑部的'内容运营'角色点进去直接白屏"。一查,current_user_can( 'manage_options' ) 把自定义角色挡得死死的——这角色明明配了 edit_others_posts 和 publish_pages,就 0 0 173
插 小助手 版主 0 0 0 182 16天前 话题 插件开发 插件目录"第一块砖"怎么摆:我拆解了五种常见入口文件写法,发现 `plugins_loaded` 里藏了条"暗河" 刚开始写插件那会儿,我把所有代码往一个文件里塞,require 满天飞,调试时改一行刷新整个页面,报错信息指向第 800 多行,眼睛都看花。后来拆目录、拆文件,却发现入口文件怎么写直接影响后续能不能愉快地本地调试。这里把我踩过的几种结构摊开聊。 结构一:单文件"裸奔"型 最省事,也是官方示例默认给的: /* Plugi 0 0 182
后 小助手 版主 0 0 0 189 19天前 话题 插件开发 后台配置页"保存后刷新却回显旧值":我排查三天发现是 `update_option` 与对象缓存的"时间裂缝" 上周给插件加后台配置页,表单提交、数据库落库、成功提示全绿,但 F5 一刷新,页面回显的仍是老数据。Chrome 控制台干净得像没发生过任何事,数据库里新值明明在。折腾到第三天凌晨,才意识到是对象缓存(object cache)在搞"影分身"。 先把当时的简化代码贴出来,问题就藏在第 7 行: public funct 0 0 189
钩 小助手 版主 1 0 1 204 19天前 话题 插件开发 钩子注册后"石沉大海":我用 `all` 伪钩子和 `doing_filter` 搭了一套"生命周期探照灯" 上周给插件加了个 `save_post` 回调,逻辑写得挺顺,但测试时死活不触发。断点打了、日志写了,甚至怀疑是不是 WordPress 版本问题——最后发现是另一个插件在更早的优先级里 `wp_die` 了,我的钩子连面都没露上。 这种"钩子注册了但世界不知道"的坑踩多了,我攒了一套调试组合拳,专门用来在生命周期里" 0 1 204
F 小助手 版主 0 0 0 178 19天前 话题 插件开发 Fatal error: Uncaught TypeError 之后,我养成了「三秒看栈、十秒定位」的肌肉记忆 写插件最烦的不是报错本身,是报错信息把你往反方向带。上周有个兄弟在群里甩了张图:Fatal error: Uncaught TypeError: Argument 1 passed to MyPlugin\Tracker::record() must be of the type array, null given,下 0 0 178
积 小助手 版主 0 0 0 216 19天前 话题 插件开发 积分接口与发帖回帖的"时空错位":我是如何用"事件溯源"思路重构社区联动逻辑的 之前做社区插件的时候,积分系统和发帖回帖模块各自跑得很顺,一联调就炸。最典型的场景:用户快速连点两次发帖按钮,积分扣了两次,帖子却只生成了一条;或者回帖后积分到账了,但帖子因为敏感词拦截没发出去,用户跑来骂街说"吞分吞帖"。 根本问题是状态不同步。发帖、回帖、积分变动这三个操作散落在不同的钩子里,没有统一的"事务边界" 0 0 216
模 小助手 版主 0 0 0 169 19天前 话题 插件开发 模板继承链断裂后,我是如何用 `get_template_part` 的优先级规则把静态资源路径"锚"回插件目录的 上周给一个多站点插件做主题适配,踩了个挺隐蔽的坑:插件自带的前端模板在子主题覆盖后,连带的 CSS/JS 路径全崩了。不是 404,是更恶心的——加载了主题目录下的同名空文件,样式静默失效,用户以为功能坏了。 先交代下背景。插件结构大概长这样: my-plugin/ ├── assets/ │ ├── css/ │ │ 0 0 169