我为四个非购物车类的 WordPress 项目开发了前端筛选功能。其中一个是招聘网站,求职者需要根据地点、职位类型和薪资范围筛选 800 个职位;一个房产目录,买家需要结合卧室数量、价格上限和房产类型进行筛选;一个食谱网站,读者可以按菜系、烹饪时间和饮食限制进行筛选;还有一个播客存档网站,听众可以按嘉宾、主题和单集时长查找想听的节目。
每次遇到的问题都一样。WordPress 可以搜索文章,也可以按一个分类法进行筛选。但是,要在自定义文章类型中,通过 AJAX 技术,在非开发人员也能轻松调整的侧边栏里,结合关键词、两个分类法和一个元值范围,这简直就是个大工程。Search & Filter Pro 正是我解决这类问题的首选插件。本指南将详细介绍它的工作原理、最近重写版本中的新增功能、它优于 FacetWP 和 SearchWP 的地方,以及它的不足之处。
Search & Filter Pro 是一款 WordPress 插件,由Code Amp开发,这家位于英国的小型工作室也是原版 Search & Filter 插件(WordPress 官方仓库中的免费版本)的开发者。Pro 版本在免费版的基础上增加了索引、高级字段类型、AJAX、与主流页面构建器集成以及与 ACF 和 Polylang 集成等功能。经过最近的一次重大重写,免费版和 Pro 扩展共享同一个后台管理界面,该界面完全基于 React 重写。
方案很简单。您可以创建一个筛选表单(包含关键词搜索、类别复选框、价格范围滑块、日期选择器和排序下拉菜单),然后将其嵌入到结果列表旁边的页面上,或者附加到现有的归档模板中。该表单会读取和写入 URL 查询参数,WordPress 查询会根据这些参数进行修改,结果可以通过页面完全刷新或通过 AJAX 更新(无需离开当前页面)来更新。表单定义以“查询”的形式存在于后台管理界面,并附加了相应的“字段”。当数据集过大,导致实时 WP_Query 响应速度过慢时,前端会从索引器中拉取数据。
对于最终用户来说,这不过是一个带有几个复选框的侧边栏,却用了这么多文字。关键在于,繁重的工作(例如合并分类表和元表、处理成千上万种排列组合、防抖动 AJAX、同步 URL 状态)都由系统自动完成。您无需WP_Query手动编写参数。
最近一次重写中发生了哪些变化(以及为什么这些变化很重要)
如果您几年前使用过 Search & Filter Pro,那么后台管理界面几乎所有内容都会有所不同。您可能还记得,旧版插件是基于短代码的:您在后台创建表单,将其复制[searchandfilter id=123]到您的页面,表单就会自动渲染。这种方法仍然适用于旧版安装,但已不再是主要的集成方式。
最近一次重大改写引入了四项改变其使用方式的内容。
查询自定义文章类型 (CPT) 已成为一级对象。查询不再仅仅是“表单”,而是对要显示的文章、结果的显示位置以及筛选字段的综合定义。您可以将同一个查询附加到主存档、查询循环块、短代码或 Elementor 文章小部件。查询是工作单元。
字段现在可以重用了。字段(例如搜索输入框、选项列表、范围滑块、日期选择器、高级排序控件)是一个独立的对象,可以附加到查询中。您可以在三个不同的查询中使用同一个类别复选框列表,而无需复制三次。
样式现在有了专属类型。新架构引入了样式预设,您可以一次性为一组字段(输入框边框、标签颜色、复选框勾选标记、范围滑块轨道)设置主题,并将其应用于所有查询。这在以前非常麻烦:每个筛选表单都有自己的内联 CSS 设置,更新品牌颜色意味着要编辑五个表单。
索引器上线了。旧插件使用实时 WP_Query 处理所有数据,这意味着每次页面加载时,都会生成一个包含 200 个分类的 Choice 列表,并将其与 wp_term_relationships 和 wp_term_taxonomy 表关联起来。当文章数量达到数千篇时,TTFB(首字节到达时间)会达到数秒。新的索引器会预先构建反向索引表(文章 -> 分类、文章 -> meta_value、文章 -> 属性),并在前端直接查询这些反向索引表。首次构建查询时,索引器会通过 WordPress 定时任务在后台运行。之后,过滤器加载时间将缩短至几毫秒。
缺点是什么?如果您是从旧版本迁移过来的,则需要重建筛选表单,因为数据模型不兼容。免费插件的迁移向导可以处理大部分工作,但对于复杂的设置,请预留半天时间。
安装、免费底座和第一小时
Search & Filter Pro 是本指南中唯一一款需要从 WordPress.org 仓库下载免费基础插件的插件。免费版search-filter插件提供核心功能(查询自定义文章类型、字段、基本搜索和选项类型、React 管理后台、区块编辑器集成)。Pro 版插件则扩展了索引器、高级字段类型、集成功能以及 AJAX 引擎。
顺序很重要。
- 首先从 WordPress.org 仓库安装并激活免费的搜索和筛选插件。依次点击“插件”、“添加新插件”、“搜索‘search-filter’”、“安装”。
- 通过插件上传 Pro zip 文件,依次点击“添加新插件”、“上传插件”,选择 zip 文件,然后激活。
首次在后台打开“搜索与筛选”功能时,您会看到一个仪表盘,其中包含“查询”、“字段”、“样式”、“设置”、“集成”和“帮助”等卡片。由于目前还没有任何查询,因此仪表盘看起来是空的。

区块编辑器集成默认开启。如果您希望 WooCommerce、ACF、Elementor 或其他页面构建器协同工作,请前往“集成”选项卡并逐个切换。大多数集成无需配置:启用 Elementor 后,字段小部件将添加到 Elementor 的小部件面板中,仅此而已。
新版后台概览:查询、字段、样式、集成
左侧导航栏的四个选项是您大部分时间都会用到的四个对象。以下是每个选项的功能介绍。
查询用于定义筛选行为。点击“添加新查询”会打开一个向导,询问两个问题:结果存储位置(动态/单页/归档/全局搜索)以及集成机制(主查询/查询循环块/短代码/Elementor 小部件)。您为查询命名并保存后,即可进入编辑界面。编辑界面包含两个选项卡:“查询设置”(位置、文章类型、要限定的分类、辅助功能选项)和“字段”(附加的筛选字段)。

字段用于放置各个筛选控件。每个字段都有数据类型(文章属性、分类、自定义字段、用户元数据)和控件类型(搜索文本、单选按钮/复选框/下拉列表、范围滑块、日期选择器、高级排序/分页/重置)。字段是独立的对象,因此您可以在三个查询中重复使用同一个“类别”复选框列表,而无需创建重复项。字段编辑器左侧是实时预览窗格,右侧是检查器面板,类似于 Gutenberg 编辑器的区块设置。

样式是字段视觉效果的预设选项。您可以定义一次品牌调色板(输入框边框颜色、焦点轮廓、复选框勾选标记、范围指示器),并将其应用于所有字段。您也可以针对每个字段单独设置样式。系统自带一个默认预设,适用于大多数主题。

“集成”页面用于切换各个第三方插件的启用状态。卡片上显示了 Block Editor、WooCommerce、ACF、Elementor、Beaver Builder、WPML、Polylang、GenerateBlocks、Relevanssi、Divi、Bricks 和 TranslatePress。部分插件默认启用(例如 Block Editor),部分插件需要先安装第三方插件才能激活,还有一些插件需要手动切换。例如,启用 Elementor 后,会在 Elementor 的小部件面板中添加新的小部件。启用 WooCommerce 后,商店存档页面将成为一个有效的筛选目标。

设置页面公开了一些全局开关:智能资源加载(仅在具有搜索和筛选字段的页面上加载 JS/CSS,这确实可以提高性能)、兼容性标志、调试工具和卸载时删除数据。

构建包含关键词、分类和薪资范围的端到端招聘网站搜索功能
让我们一步步完成整个构建过程,把上面抽象的概念变成你可以发布的东西。同样的模式也适用于房源列表、菜谱、播客目录或其他任何内容。
步骤 1:注册文章类型和分类。如果您希望非开发人员稍后也能编辑文章类型,可以使用自定义文章类型用户界面 (Custom Post Type UI);或者,您也可以使用代码注册文章类型register_post_type()。创建一个名为“Job”的文章类型,public => true并has_archive => true为其添加两个分类:job_location(Locations) 和(Full-time, Part-time, Contract, Internship)。然后,通过Advanced Custom Fields Projob_type在“Job”文章类型上添加一个名为“Salary”的元字段,字段类型为“数字”。
步骤 2:添加一些内容。如果文章类型为空,筛选表单就毫无意义。至少添加 30 个职位,这样筛选器才能真正发挥作用。WP-CLI 是最快的方法:wp post generate --post_type=job --count=30然后wp term generate job_location --count=8,对 job_type 也类似。
步骤 3:创建查询。依次点击“搜索和筛选”、“查询”、“添加新查询”。将其命名为“职位搜索”。选择“位置”=“存档”,“存档类型”=“帖子类型”,“帖子类型”=“职位”,“查询”=“主查询”。保存。
步骤 4:添加关键字字段。在查询的编辑屏幕中,切换到“字段”选项卡,单击“添加新字段”。选择“搜索”>“文本”,将其命名为“搜索”,占位符为“搜索职位…”。保存。

步骤 5:添加位置复选框列表。添加新字段,选择“选项”>“复选框”,数据类型 = 分类,数据源 = job_location。标签为“位置”。这将把分类中的每个术语都提取为一个复选框。保存。
步骤 6:添加就业类型单选按钮。添加新字段,选择“选项”>“单选按钮”,数据类型 = 分类,数据源 = job_type。标签为“就业类型”。选择“单选按钮”是因为一份工作通常只有一种类型,而不是多种。
步骤 7:添加薪资范围。添加新字段,选择“范围”>“滑块”,数据类型 = 自定义字段,字段键 = salary(或您的 ACF 键),最小值 = 30000,最大值 = 250000,步长 = 5000。标签为“薪资范围”。Pro 索引器会扫描所有职位发布的 meta_value 并构建反向索引,这样滑块就不必在每次按键时都实时查询庞大的表。
步骤 8:添加高级控件。添加新字段,选择“高级”>“排序”。添加“日期(最新在前)”、“薪资(从高到低)”、“职称(AZ)”等选项。添加另一个“高级”>“重置”按钮。添加另一个“高级”>“结果计数”按钮。
步骤 9:样式设置(可选)。打开“样式”选项卡,选择“默认”预设,进行编辑。将焦点轮廓设置为您的品牌颜色,将复选框勾选框设置为您的强调色。保存。现在,使用此预设的每个查询中的每个字段都将保持一致。
步骤 10:在前端进行验证。访问 /jobs/(或文章类型归档所在的任何位置)。您应该会在归档模板上看到表单渲染。应用一个筛选条件,结果更新。应用两个筛选条件,结果范围缩小。
如果表单在归档页面无法正确显示,则说明主题的归档模板没有the_archive_title()以可识别的方式调用或渲染主查询。您有两种选择:将查询集成切换到“查询循环块”,并在自定义页面上使用 Gutenberg 编辑器的查询循环块;或者在[searchandfilter field="N"]手动运行主查询的页面上使用旧版短代码。字段编辑器右上角有一个“复制短代码”按钮,点击即可获得完全正确的标记。

这就是整个构建过程。最终在实际存档中呈现的状态:关键词输入框、地点复选框、职位类型单选按钮、薪资范围滑块、排序下拉菜单、重置按钮,以及卡片上方的结果计数。

AJAX 与页面重新加载:它们各自的成本是多少?
这款专业版插件允许你切换筛选器更新是触发页面完全重新加载还是通过 AJAX 切换。两者各有优劣,在我接手的每个项目中,我都见过有人选错了。
页面重新加载是默认行为。当用户点击复选框时,表单提交,URL 会更新查询参数(例如 `–selected-url` ?_sf_location=london&_sf_type=full-time),然后页面重新加载。优点:每个筛选组合都是一个真实的 URL,Google 可以抓取;浏览器后退按钮有效;WordPress 查询在服务器端运行,比任何 AJAX 操作都快。缺点:页面每次更改都会闪烁,用户会丢失滚动位置,而且在速度较慢的服务器上,重新加载本身需要 800 毫秒以上。
AJAX无需离开当前页面即可更新搜索结果。优点:响应迅速,滚动位置保持不变,无闪烁。缺点:筛选组合并非总能生成可抓取的 URL(需要显式启用 pushState),服务器仍需执行查询并进行 JSON 序列化/反序列化,且故障情况更为严重(响应缓慢且无加载指示器,会让人误以为网站已损坏)。
我遵循以下规则:如果筛选条件组合对搜索引擎优化 (SEO) 至关重要,则默认使用可抓取的 URL 进行页面重新加载。例如招聘网站、房产列表、电商网站存档页面等。谷歌需要找到这些/jobs/?location=london&type=full-time页面,并返回一个包含真实内容的 200 页面。
如果筛选器只是单个页面上的一个用户界面功能,无需被索引,则可以使用 AJAX。例如内部仪表盘、边输入边搜索的界面、模态筛选抽屉等。
启用 AJAX 前,务必先测试“无结果”状态。这是用户开始尝试各种组合后最常遇到的页面状态。
Search & Filter Pro 开箱即用,支持按任意post_meta键进行筛选。您只需进入“选择”或“范围”字段,选择“自定义字段”作为数据类型,输入元键,索引器就会构建一个包含 (meta_value, post_id) 条目的反向索引。
ACF 是一项一流的集成。在“集成”中启用 ACF 卡片后,数据源下拉列表中会以友好名称显示 ACF 字段键(无需您手动输入原始元键)。它还能处理 ACF 特殊的序列化值:重复字段、分组子字段、多选值、分类字段和文章对象引用。该集成/search-filter-pro/v1/acf/在管理 UI 下添加了三个 REST 端点,用于枚举 ACF 字段组和字段。
Pods 和 MetaBox 虽然不是一流的集成,但它们post_meta像 ACF 一样存储值,因此您可以使用带有原始元键的自定义字段,而且它能正常工作。
以下功能不太适用:ACF 关系字段和文章对象字段。Search & Filter Pro 可以根据存储在元数据中的文章 ID 进行筛选,但如果没有自定义开发者钩子,它无法将相关文章的标题显示为选项标签。虽然有一个过滤器(search-filter/fields/control/options)允许您重写选项标签,但您必须编写解析器。
对于更复杂的情况,可以使用每个字段的“自定义”数据类型,它允许您通过筛选钩子提供自己的 SQL 语句或选项列表。当您执行 UI 未预料到的操作时,可以使用此功能:例如,按“当前用户收藏的帖子”筛选、按“本周末发生的活动”筛选、按计算字段筛选。
Search & Filter Pro、FacetWP、SearchWP 和 Posts Table Pro:各有千秋。
四种工具,四项工作。每周都会挑错垃圾。
许可定价。Search & Filter Pro 零售价为单站点每年 79 美元,5 个站点每年 149 美元,或单站点终身许可每年 249 美元。FacetWP单站点每年 99 美元,无限站点每年 249 美元。SearchWP标准版每年 99 美元,代理版每年 399 美元。Posts Table Pro单站点每年 74 美元,无限站点每年 239 美元。仅从零售价来看,Search & Filter Pro 和 Posts Table Pro 并列最低。
前端插件包大小。我在一个纯净的 Twenty Twenty-Five 系统上测试了这些插件包,页面上只有一个筛选表单。Search & Filter Pro 插件增加了 28KB 的压缩版 JS 和 6KB 的压缩版 CSS。FacetWP 插件增加了 81KB 的 JS 和 24KB 的 CSS。SearchWP 插件增加了 12KB 的 JS(主要是服务器端代码)和 4KB 的 CSS。Posts Table Pro 插件增加了 67KB 的 JS(DataTables)和 11KB 的 CSS。如果前端插件大小对于性能要求极高的项目至关重要,那么 SearchWP 和 Search & Filter Pro 是更轻量级的选择。
索引要求。Search & Filter Pro 现在通过 WP-cron 增量构建索引,并在运行时查询索引,因此您无需记住“内容更改后重新索引”的手动步骤。FacetWP 需要按计划(或批量导入后)显式地重新索引,这在拥有 10 万篇文章的网站上可能需要 10-30 分钟,并且在完全重建期间会锁定管理员帐户。SearchWP 也会索引,但仅索引搜索关键字内容,而不索引筛选条件(它优先考虑相关性)。Posts Table Pro 完全没有单独的索引(它通过 DataTables 在客户端加载所有内容,这就是为什么它在处理大约 5000 行数据后就会变得非常缓慢的原因)。
自定义字段支持。Search & Filter Pro 开箱即用,支持任何 post_meta,并提供一流的 ACF 集成。FacetWP 要求您通过代码或用户界面为每个 meta 键显式定义筛选条件,这种方式虽然更死板,但也更直观。SearchWP 的 meta 筛选支持有限:它可以将 meta 包含在关键词搜索中,但不能作为独立的筛选条件。Posts Table Pro 将 meta 显示为表格列,并使用文本搜索进行筛选,这种方式更像是“电子表格”而非“Airbnb 搜索”。
筛选器界面灵活。Search & Filter Pro 提供单选按钮、复选框、下拉菜单(带搜索功能)、范围滑块、日期选择器和自动完成搜索。FacetWP 增加了位置搜索、层级分类筛选和“工具提示滑块”。SearchWP 几乎不可见(它调整 WordPress 的搜索行为,没有自己的前端界面)。Posts Table Pro 是一个可排序的表格,带有每列下拉菜单。
WooCommerce 商店筛选功能。这四款工具都支持 WooCommerce,但设计理念各不相同。Search & Filter Pro 为商店存档页面添加了查询类型,并支持对产品属性、类别和价格进行筛选。FacetWP 则在商店筛选方面最具特色,拥有专门的 WooCommerce 分面功能。FiboSearch和Relevanssi Premium则是专门针对 WooCommerce 搜索栏的筛选工具。
我的简短版本:Search & Filter Pro 用于轻量级设置的一般筛选,FacetWP 用于大型商店的复杂筛选用户体验,SearchWP 用于修复糟糕的关键词搜索,Posts Table Pro 用于实际的表格数据展示。
不要在未启用防抖功能的情况下启用点击提交:原因如下
查询检查器中有一个名为“字段更改时提交表单”的设置。启用后,每次点击复选框、在搜索框中输入任何内容、每次拖动范围滑块都会触发一个请求。启用后感觉很棒。网站会随着您的勾选而更新,无需提交按钮。
然后你的流量翻倍,你的共享主机就崩溃了。
事情是这样的:用户打开一个包含五个选项的筛选器。他们勾选第一个复选框(一次请求)。他们勾选第二个复选框(又一次请求)。他们拖动一个范围滑块(每次滑块值改变都会产生一次请求,在触摸屏上,每次拖动可能产生 30 多次事件)。他们在关键词搜索框中输入三个字母(三次请求)。在他们阅读搜索结果之前,就已经发生了 20 次交互。在页面重新加载的架构下,这意味着 20 次完整的 WordPress 页面渲染。在 AJAX 架构下,这意味着 20 次后台 AJAX 调用,每次调用都会运行 WordPress 查询并将文章序列化为 JSON。
解决方法要么是保留“提交”按钮(默认选项,也是我通常的选择),要么,如果您必须使用更改时提交,则需要为文本输入框和范围滑块添加防抖功能。插件中有一个 JavaScript 过滤器钩子,会search-filter-pro/frontend/before_request在 AJAX 提交之前触发。您可以在那里进行防抖处理:
let sfDebounceTimer;
wp.hooks.addFilter('search-filter-pro/frontend/before_request', 'mytheme/debounce', function(args, field) {
if (field.type === 'search' || field.type === 'range') {
clearTimeout(sfDebounceTimer);
return new Promise(resolve => {
sfDebounceTimer = setTimeout(() => resolve(args), 350);
});
}
return args;
});350毫秒是最佳值。太短会感觉卡顿,太长则会感觉程序崩溃。
另一个相关的反模式是:将所有分类法都作为筛选器展示出来。如果一个内容网站有五个分类法,你的侧边栏看起来就像一份税表。选择对用户完成任务最重要的两到三个分类法。将其余分类法隐藏在可折叠的“高级筛选器”开关中,或者干脆省略它们。筛选器的用户体验是少数几个“少即是多”的例子之一。
索引器:Pro 如何快速查询大型数据集
这是大多数产品页面都会忽略的部分。之所以要重写,是因为旧的实时查询方法无法扩展。在一个拥有 5 万篇文章、两个分类法和一个元过滤器的网站上,post_content即使使用了正确的 MySQL 索引,一个前端过滤器请求也需要连接三个表,对数据执行 SUBSTR LIKE 操作,并且耗时 2.5 秒才能返回结果。这指的是在 HTML 数据加载之前完成的 TTFB(首字节到达时间)。
专业版索引器会预先构建反向索引表。保存查询时,后台任务会扫描所有匹配的帖子,并将 (post_id, field_id, value) 行写入索引表wp_search_filter_pro_index。运行时查询只需WHERE field_id = X AND value IN (...)针对单个索引表执行简单的操作,即可在几毫秒内返回结果。
索引器以增量方式运行。新文章在 [日期] 索引save_post,更新的术语在 [日期] 索引set_object_terms,更新的元数据在[updated_post_meta日期] 索引。后台任务运行器会将这些数据分批处理成安全的块,以避免批量导入导致请求阻塞。内存管理通过search-filter-pro/task_runner/batch_size过滤器进行(默认值基于 [日期] 动态调整wp_max_memory_limit)。
如果需要手动重建(例如在迁移数据后,或在影响索引字段的设置更改后),可以在“设置”>“索引器”下找到“重建”按钮。此外,还可以使用命令行界面 (CLI) 进行重建。REST 端点位于 [此处应填写 REST 端点地址]、[此处应填写REST端点地址]wp search-filter-pro index rebuild和[wp search-filter-pro index status此处应填写 REST 端点地址] 。/wp-json/search-filter-pro/v1/indexer/rebuild/indexer/resume/indexer/pause
索引设计的一个副作用是:无需重新运行查询即可获得准确的筛选计数。“选择”字段可以显示“伦敦 (12)、柏林 (8)、东京 (3)”,因为这些计数在同步时被反规范化到索引中。FacetWP 也采用了这种做法,而 SearchWP 则没有。
索引位于您的自定义表$wpdb->prefix(默认表wp_search_filter_pro_index和一些辅助表)中。它会随着文章数量的增加而增长:粗略的经验法则是,每个索引的(文章,字段)对占用 1KB 的空间,因此一个拥有 1 万篇文章和 5 个索引字段的网站大约占用 50MB 的空间。这在现代主机上不算小,但也不算巨大。
实际应用案例
我已经使用 Search & Filter Pro 完成了五个项目。
包含 800 条招聘信息的招聘网站。筛选条件:关键词、地点(分类)、职位类型(分类)、薪资范围(ACF 元数据)、发布日期(仅排序)。前端用户体验:侧边栏带有固定筛选器,结果显示在主列,点击提交按钮时触发 AJAX 提交(而非更改时提交)。包括内容填充在内的总构建时间:两天。薪资范围的设置最为棘手,因为 ACF 默认将该值存储为字符串,直到我将其更改为数字类型。
房地产代理的房源目录。共 200 条房源信息。筛选条件:城市(分类)、房产类型(分类)、卧室数量(元数据)、浴室数量(元数据)、价格范围(元数据)。小贴士:我使用了单选按钮(1、2、3、4+)来筛选卧室数量,而不是使用范围滑块。滑块看起来更简洁,但对于房间数量这类具体选项,单选按钮更清晰明了。
拥有 1200 道菜谱的食谱博客。筛选条件:菜系(分类)、菜式(分类)、饮食标签(分类,多选)、烹饪时间(元数据,范围)。饮食标签多选功能是关键:“纯素 AND 无麸质 AND 30 分钟以内”之所以有效,是因为 Search & Filter Pro 默认使用 AND 而不是 OR 连接多值选项。(每个字段的 AND 逻辑均可单独配置。)
播客目录。共 400 集,分为两季。筛选条件:嘉宾(我为嘉宾创建的自定义分类)、主题(分类)、时长范围(以分钟为单位的元数据)。嘉宾分类及其自动补全搜索功能是杀手锏:如果用复选框来管理 200 多位嘉宾,那将非常不便,但“搜索 > 自动补全”字段类型(数据类型为“分类”)使其变得立即可用。自动补全功能会向 REST 服务发送请求/search-filter-pro/v1/autocomplete/search并返回匹配的术语名称。
适用于学习管理系统 (LMS) 的课程目录。包含 80 门课程,并按级别(初级/中级/高级)、主题、讲师和时长范围进行分类。课程交付与LearnDash LMS集成,目录浏览则使用 Search & Filter Pro。“讲师”分类同时兼作重定向目标:点击课程页面上的讲师姓名,即可跳转至该讲师筛选后的课程目录。
开发者参考:钩子、过滤器、REST 端点、类
这使得 Search & Filter Pro 成为一个对开发者友好的插件,而不是一个“无代码”的黑盒。以下是一些值得了解的钩子和过滤器,还有更多。
字段级 URL 参数重写。默认情况下,字段在 URL 中以 `<field>` 的形式公开_sf_<field_slug>。要重命名:
add_filter( 'search-filter/fields/field/url_name', function( $url_name, $field ) {
if ( $field->get_attribute( 'name' ) === 'location' ) {
return 'loc';
}
return $url_name;
}, 10, 2 );这样就?_sf_location=london变成了?loc=london……这对于SEO友好的URL和更短的分享链接非常有用。
范围字段自动检测自定义字段。当范围字段的数据源为自定义字段时,Pro 会尝试自动检测元键。要覆盖此设置:
add_filter( 'search-filter/fields/range/auto_detect_custom_field', function( $key, $attributes ) {
if ( $attributes['name'] === 'salary' ) {
return 'job_salary_usd'; // your ACF key
}
return $key;
}, 10, 2 );Range 字段 WP_Query 参数。修改 Range 字段生成的 meta_query:
add_filter( 'search-filter/fields/range/wp_query_args', function( $args, $field ) {
// Force numeric comparison even if meta was stored as string
if ( isset( $args['meta_query'][0]['type'] ) ) {
$args['meta_query'][0]['type'] = 'NUMERIC';
}
return $args;
}, 10, 2 );选择字段选项。重写或筛选选择字段的选项列表:
add_filter( 'search-filter/fields/control/options', function( $options, $field ) {
if ( $field->get_attribute( 'name' ) === 'category' ) {
// Remove an unwanted category from the list
return array_filter( $options, fn( $o ) => $o['value']!== 'uncategorized' );
}
return $options;
}, 10, 2 );自动完成建议。为“搜索 > 自动完成”字段类型注入您自己的建议源:
add_filter( 'search-filter-pro/field/search/autocomplete/suggestions', function( $suggestions, $search, $field ) {
// Your custom suggestion logic
$custom = array(
array( 'label' => 'Sample suggestion', 'value' => 'sample' ),
);
return array_merge( (array) $suggestions, $custom );
}, 10, 3 );索引器缓存开关。禁用全站索引器查询缓存:
add_filter( 'search-filter-pro/indexer/query/enable_caching', '__return_false' );索引器批处理大小。覆盖索引重建的默认批处理大小:
add_filter( 'search-filter-pro/task_runner/batch_size', function( $size ) {
return 50; // smaller batches for shared hosts with low memory
});结果模板路径。使用短代码集成时,可指定用于渲染结果的模板:
add_filter( 'search-filter-pro/shortcodes/results/template_path', function( $path, $query_id ) {
if ( $query_id === 5 ) { // your custom Job Search query ID
return get_stylesheet_directory(). '/templates/job-results.php';
}
return $path;
}, 10, 2 );查询生命周期操作。围绕结果查询执行您自己的代码:
add_action( 'search-filter-pro/shortcodes/results/query/start', function( $query_id ) {
// e.g. start a timer
});
add_action( 'search-filter-pro/shortcodes/results/query/finish', function( $query_id ) {
// e.g. log to a perf monitor
});索引器生命周期操作。用于监听索引器事件:
search-filter-pro/indexer/init_sync_data/startsearch-filter-pro/indexer/init_sync_data/finishsearch-filter-pro/indexer/run_task/startsearch-filter-pro/indexer/run_task/finishsearch-filter-pro/indexer/query/result_lookup/startsearch-filter-pro/indexer/query/result_lookup/finish
REST 端点。全部位于/wp-json/search-filter-pro/v1/:
/indexer(GET)– 索引器状态/indexer/rebuild(POST)– 触发完全重建/indexer/resume(POST)– 恢复已暂停的索引器/indexer/pause(POST)——暂停运行索引器/autocomplete/search(GET)– 自动完成建议/license/*– 许可证激活/停用/task-runner/*– 后台任务状态和控制/acf/*– 管理用户界面的 ACF 字段枚举
值得了解的类。全部位于Search_Filter_Pro命名空间下,自动加载自includes/:
Search_Filter_ProIndexer– 索引器入口点Search_Filter_ProCache– 分层缓存层(带 APCu 回退)Search_Filter_ProTask_Runner– 后台工作助理Search_Filter_ProFeatures– 功能切换层Search_Filter_ProIntegrations– 第三方集成加载器Search_Filter_ProDatabaseQuery_Optimizer– SQL 查询优化器Search_Filter_ProFieldsRange– 靶场实施
该架构采用命名空间,并符合 PSR-4 标准,因此无需修改核心代码即可扩展单个功能。仅凭这一点,它就优于同时期仍在使用全局函数和单例反模式的插件。
性能、兼容性以及值得注意的陷阱
从生产过程中总结出的一些宝贵经验。
智能资源加载默认开启,建议保持开启状态。它会跳过加载没有搜索和筛选字段的页面上的前端 JS 和 CSS。检查速度很快,在没有筛选表单的页面上节省的资源是实实在在的,但失败的情况也确实存在(如果您在运行时通过 PHP 而不是通过后台管理界面构建字段,智能资源加载将无法识别,您的字段将无法加载其 JS)。要强制加载这些字段,请add_filter( 'search-filter/frontend/should_load_assets', '__return_true' );在 functions.php 文件中添加相应的代码。
索引器可能会因为 cron 配置错误而停止运行。WordPress基于请求的 cron任务会触发索引器的后台任务,因此在低流量网站上,索引器可能几个小时都不会运行。如果您在“设置”页面中看到“索引器正在运行”状态持续过长时间,请检查该状态wp-cron.php是否真的被触发(大多数托管主机都会禁用 WordPress cron 任务,而是通过系统 cron 任务运行索引器)。如果您需要立即运行索引器,可以点击“重建”按钮强制执行同步运行。
WPML 和 Polylang 改变了索引语义。每种语言都有自己的索引。切换语言后,同一个字段可能会返回不同的计数。这是正确的行为,但在测试时可能会让人感到困惑。
WooCommerce 的可变产品比较特殊。如果按属性“颜色 = 红色”筛选,匹配到的将是父级可变产品,而不是其变体。这是 WooCommerce 的正常行为,并非 Search & Filter Pro 的 bug,但值得注意。
AJAX 归档页面的分页功能可能会失效。如果您的主题使用paginate_links()了自定义的分页基,AJAX 响应可能无法正确重新生成分页。解决方法是使用“高级”>“分页”设置(插件可以正确重新渲染),或者编写一个自定义的 JS 处理程序,在每次 AJAX 切换后重新绑定分页点击事件。
旧版[searchandfilter id=N]短代码已在当前版本中移除。新的短代码[searchandfilter field="N"]用于渲染单个字段。要渲染完整的查询,您可以将字段短代码嵌入到查询主查询所在的页面中,或者使用查询循环块,或者使用 Elementor 小部件。
缓存插件需要一些提示。WP Rocket、LiteSpeed Cache 以及任何其他页面缓存插件都会缓存筛选结果,除非您明确告知它们不缓存。插件的兼容性设置会自动检测 WP Rocket 并添加相应的排除项。对于其他插件,请将 Search & Filter Pro 使用的 URL 参数(_sf_*)添加到缓存插件的“忽略查询字符串”列表中,或者直接对包含筛选表单的页面禁用缓存。
Search & Filter Pro 做不到的事情(以及当你最终还是会选择 FacetWP 的时候)
实话实说。有三件事,如果需要的话,会让我选择其他工具。
按距离/生成式引擎优化(GEO)半径搜索。 “显示波士顿方圆 25 英里内的工作。” Search & Filter Pro 可以按城市分类进行筛选,但它不支持经纬度半径计算。FacetWP 有一个可以实现此功能的“距离”筛选器。SearchWP 有一个可映射的生成式引擎优化(GEO)搜索扩展。如果您的项目需要真正的“附近”搜索,那么这些是最佳选择。
层级分类法,父级可折叠。默认情况下,分类选择字段是扁平的。子类别会以单独的复选框形式显示在其父级旁边。您可以使用 CSS 来调整它们的视觉缩进,但要通过展开/折叠父级来显示/隐藏子级则需要自定义 JS 代码。FacetWP 提供了一个“层级结构”分面,可以原生支持此功能。
毫秒级实时索引更新。索引器由 cron 定时任务驱动,采用增量式更新,这意味着内容更改与筛选器反映更改之间存在轻微延迟(通常为 30 秒到几分钟)。对于食谱博客来说,这没问题。但对于实时股票行情来说,就不合适了(而且 Search & Filter Pro 本身也不是合适的工具)。
此外,文档也存在不足。searchandfilter.com上的官方文档涵盖了基础知识,但开发者参考文档却比 FacetWP 的要简略得多。你会发现自己需要阅读插件源代码(尤其是 `<head>`includes/features/class-shortcodes.php和 ` includes/integrations/<head>`)来解答“如何自定义 X”这类问题,这比你预想的要频繁得多。
管理后台生成器的用户界面虽然经过重写后有了很大的改进,但与 WPForms 或 Gravity Forms 的精致程度相比,仍然略逊一筹。不算差,只是明显是由一家小型工作室开发,并且通过 Chrome 浏览器发布功能。
常问问题
为什么我的自定义字段没有显示为可筛选选项?
两个常见原因。首先,该字段必须实际在某些文章中保存了值;空的 meta_key 不会显示。其次,索引器自添加该字段以来至少需要运行一次;索引器负责填充选项下拉列表。通过“设置”>“索引器”>“重建”手动触发重建。如果您正在使用 ACF,请确保在“集成”下启用 ACF 集成。
我可以在同一页面上放置多个搜索表单吗?
是的,但有一些注意事项。同一页面上的多个字段短代码如果属于不同的查询,则可以正常工作。如果它们属于同一个查询,则会生成两个表单,这两个表单都会提交到同一个 URL 状态,这有时正是您想要的(例如,顶部栏和侧边栏)。对于同一页面上的两个独立搜索(播客筛选和食谱筛选),请定义两个具有不同查询集成目标的查询,这样它们就不会冲突。
Search & Filter Pro 是否支持无限滚动存档?
算是吧。这个插件能很好地处理标准分页。无限滚动取决于主题:如果你的主题使用了 Jetpack Infinite Scroll 或类似的模式,AJAX 切换可能会导致无限滚动处理程序出错。解决方法是将查询集成切换到非 AJAX(页面重新加载),这样可以保留浏览器原生的后退按钮和 URL 状态。或者,你也可以在 Search & Filter Pro 的after_request事件和你的无限滚动重新初始化钩子之间编写一个自定义的 JS 桥接。但这并非易事。
为什么我的筛选器会导致 WooCommerce 商店分页功能失效?
WooCommerce 的商店分页功能使用了一个自定义重写规则(/shop/page/2/),该规则与 Search & Filter Pro 的查询参数冲突。解决方法是启用 WooCommerce 集成卡片(该卡片会识别此问题),并使用 WooCommerce 短代码products代替默认的商店存档,或者在设置为“商店”页面的自定义页面上使用查询循环模块。直接与默认商店存档集成在大多数情况下都能正常工作,但某些特殊情况下会出现问题。
如何为帖子设置日期范围筛选器?
添加一个“日期 > 范围”字段,数据类型为“文章属性”,数据源为“文章日期”。该字段将按文章的发布日期进行筛选。要按存储为 meta_value 的自定义日期字段(例如 ACF 中的“event_date”字段)进行筛选,请使用“日期 > 范围”字段,数据类型为“自定义字段”,字段键为“event_date”。请确保 meta_value 以Y-m-d字符串格式存储,因为比较是基于字符串的;ACF 日期选择器在配置为该返回格式时可以正确执行此操作。
Search & Filter Pro 会降低我的网站速度吗?
说实话,可能不行,但有两点需要注意。前端 JS 文件很小(压缩后约 28KB),而且智能资源加载机制会将其从不需要的页面中移除。索引器会在内容更改时通过 WP-cron 添加后台加载,这在低流量网站上几乎察觉不到,但在高流量网站(例如每小时保存 1000 多篇文章)上可能会比较明显。search-filter-pro/task_runner/batch_size如果发现流量高峰,请在共享主机上降低加载量。
它能处理翻译后的内容吗?
是的。WPML 和 Polylang 集成会按语言建立索引,因此法语筛选器只会显示法语文章。这些集成还会自动翻译字段标签和描述,这对于多语言网站来说虽然只是一个小小的功能,但却能节省大量时间。
总结
当项目需要“用户能够根据几个属性筛选内容列表”且技术栈已包含 WordPress 时,我就会选择 Search & Filter Pro。它的管理界面并非最完善,文档也只能说一般,与 WooCommerce 商店存档的集成也存在一些特殊情况,需要花费一个小时才能解决。但它的索引速度确实很快,AJAX 引擎无需编写 JavaScript 代码即可工作,开发者接口也十分合理,而且价格也合适。
与 FacetWP 的对比显而易见。当筛选用户体验本身就是产品时(例如 Airbnb 那种拥有数千个选项的多面抽屉式筛选器),FacetWP 是最佳选择。而当筛选功能只是大型网站(例如兼具博客功能的招聘网站、兼具经纪营销功能的房产目录网站、需要改进归档用户体验的食谱博客)的筛选功能时,Search & Filter Pro 则是理想之选。选择工具时,要考虑实际应用场景,而不是演示 GIF。
如果你一直用手动编写WP_Query参数、自定义短代码和 jQuery 来进行筛选,那就别再这么做了。Search & Filter Pro 是完成这项工作的最便捷方案,而且全新的索引器架构意味着你无需像以前那样,在处理大型数据集时承受性能瓶颈。只需抽出一个下午,构建表单,然后发布即可。


