WP DEVELOP

EP134. “敏感词过滤核心逻辑与 Options 子页收尾”

首页 WordPress 开发课程 插件开发 CH1:PHP 基础 · EP134
约 12 分钟· #EP134#插件开发 CH1:PHP 基础
🔒 登录后可标记已读

完成插件最后两块拼图:① 把逗号分隔的敏感词字符串转成数组、去除多余空白,用 str_ireplace() 不分大小写地替换掉正文里出现的这些词;② 给 Options 子页面用上一个插件学过的 Settings API(跟 Words List 页手写表单的做法刻意不同,用来示范两种方式可以在同一个插件里混用)实现「自定义替换文字」设置,并把这个值接回过滤逻辑里,同时补上手动调用 settings_errors() 才会出现的绿色保存成功提示。


涉及文件

  • wp-content/plugins/our-word-filter-plugin/index.php (修改)

代码实现

__construct():只在敏感词列表非空时才挂过滤器

function __construct() {
  add_action('admin_menu', array($this, 'ourMenu'));
  add_action('admin_init', array($this, 'ourSettings'));
  if (get_option('plugin_words_to_filter')) add_filter('the_content', array($this, 'filterLogic'));
}

filterLogic():核心过滤逻辑

function filterLogic($content) {
  $badWords = explode(',', get_option('plugin_words_to_filter'));
  $badWordsTrimmed = array_map('trim', $badWords);
  return str_ireplace($badWordsTrimmed, esc_html(get_option('replacementText', '****')), $content);
}

ourSettings() / replacementFieldHTML():Options 子页用 Settings API 注册「替换文字」设置

function ourSettings() {
  add_settings_section('replacement-text-section', null, null, 'word-filter-options');
  register_setting('replacementFields', 'replacementText');
  add_settings_field('replacement-text', 'Filtered Text', array($this, 'replacementFieldHTML'), 'word-filter-options', 'replacement-text-section');
}

function replacementFieldHTML() { ?>
  <input type="text" name="replacementText" value="<?php echo esc_attr(get_option('replacementText', '***')) ?>">
  <p class="description">Leave blank to simply remove the filtered words.</p>
<?php }

optionsSubPage():输出 Settings API 表单,补上成功提示

function optionsSubPage() { ?>
  <div class="wrap">
    <h1>Word Filter Options</h1>
    <form action="options.php" method="POST">
      <?php
        settings_errors();
        settings_fields('replacementFields');
        do_settings_sections('word-filter-options');
        submit_button();
      ?>
    </form>
  </div>
<?php }

关键改动点:

  • explode(',', $string) 把逗号分隔的字符串切成数组;array_map('trim', $array) 对数组里每一项都跑一遍 trim(),去掉每个词前后可能多打的空格——这两步组合处理了「用户输入格式不规整」的容错
  • str_ireplace($search_array, $replace, $subject):结尾的 i 表示 case-insensitive(不分大小写)替换,跟普通的 str_replace() 不同——这样用户敏感词列表里写的是小写,也能过滤掉正文里出现的大写/首字母大写版本
  • esc_html(get_option('replacementText', '****')):替换文字本身也是从数据库取出的动态值,输出前一样要转义;get_option() 的默认值从最初测试用的「四个星号」延续下来,作为「用户还没在 Options 页设置过替换文字」时的兜底显示
  • add_filter('the_content', ...) 这一行被包在 if (get_option('plugin_words_to_filter')) 判断里——如果敏感词列表是空的,压根不需要给 the_content 挂过滤器,省掉每次渲染文章都要执行一次无意义过滤运算的开销
  • Options 子页面刻意换用第一个插件(字数统计)学过的 Settings API 而不是延续 Words List 页「手写 PHP 处理提交」的做法——这是刻意的教学安排,说明同一个插件内部完全可以按每个页面的具体需求,各自选择最合适的实现方式,不需要整个插件统一成一种风格
  • settings_errors():Settings API 生成的页面默认不会自动显示保存成功的提示(不像第一个插件里用的「Settings 官方菜单」那样自动处理),因为这个页面是挂在自定义顶级菜单下、不是官方 Settings 菜单体系的一部分,所以需要手动调用一次 settings_errors() 才会显示绿色的「已保存」提示

[截图:前台博客文章正文里,敏感词被替换成星号(或自定义替换文字)后的实际效果]

[截图:wp-admin Word Filter Options 子页面,Filtered Text 输入框与保存后的绿色成功提示]


Hook / Function 速查

名称类型用途
explode($separator, $string)PHP 内建 function按分隔符把字符串切成数组
array_map($callback, $array)PHP 内建 function对数组每个元素执行同一个函数,返回处理后的新数组
str_ireplace($search, $replace, $subject)PHP 内建 function不区分大小写的字符串批量替换
settings_errors()WP 内建 function输出 Settings API 相关的保存成功/失败提示消息,非官方 Settings 菜单页面需要手动调用

常见坑

  • str_replace() 而不是 str_ireplace()——普通版本区分大小写,用户列表里的小写敏感词不会匹配到正文里首字母大写或全大写的版本
  • 忘记 trim() 处理用户输入的敏感词列表——逗号后面多打的空格会让每个「词」前面多一个空格字符,导致匹配不到正文里紧贴着的实际单词
  • 挂在自定义顶级菜单下的 Settings API 页面忘记手动调用 settings_errors()——保存明明成功了,但用户看不到任何提示反馈,会以为操作没有生效

延伸 / 后续讲座会用到

到这里,插件开发第一章(PHP 基础)圆满结束:两个完整的插件(字数统计、敏感词过滤)涵盖了插件骨架、Settings API 自动生成表单、手写表单+Nonce 安全校验、自定义菜单与图标、国际化等核心技能。下一章切换到 JavaScript,会做两个自定义 Gutenberg Block 类型(互动问答题、动态拉取教授信息的 Callout)。


Sources

Udemy:

  • Become a WordPress Developer: Unlocking Power With Code — Section 23, EP134