Divi博客模块自定义多条件筛选功能开发求助
解决方案:Divi自定义文章类型多维度筛选实现
基于Divi子主题开发WordPress站点,已通过ACF创建recipes自定义文章类型,搭配recipe_label、recipe_categories自定义分类法及recipe_short-description等字段,修改Blog模块后已能正常展示内容,但筛选功能存在以下问题:
- 现有PHP方案仅支持单一分类/标签筛选,无法实现多选标签、多选分类或标签+分类组合筛选
- Ajax/JS动态筛选方案触发404错误,完全失效
- 无法使用高级付费插件,站点暂无法公开访问
以下是完整的免费解决方案:
1. 修改PHP筛选逻辑(支持多选+组合筛选)
替换原有的custom_recipe_filter_query函数,新增对recipe_categories的支持,同时处理多选参数:
function custom_recipe_filter_query($query) { // 仅处理前台主查询,且限定在recipes归档页 if (is_admin() || !$query->is_main_query() || !is_post_type_archive('recipes')) { return; } $tax_query = array('relation' => 'AND'); // 所有筛选条件需同时满足,需OR关系可修改为'OR' // 处理recipe_label多选 if (isset($_GET['recipe_label']) && !empty($_GET['recipe_label'])) { $labels = is_array($_GET['recipe_label']) ? $_GET['recipe_label'] : array($_GET['recipe_label']); $labels = array_map('sanitize_text_field', $labels); $tax_query[] = array( 'taxonomy' => 'recipe_label', 'field' => 'slug', 'terms' => $labels, 'operator' => 'IN' // 匹配选中标签中的任意一个 ); } // 处理recipe_categories多选 if (isset($_GET['recipe_categories']) && !empty($_GET['recipe_categories'])) { $categories = is_array($_GET['recipe_categories']) ? $_GET['recipe_categories'] : array($_GET['recipe_categories']); $categories = array_map('sanitize_text_field', $categories); $tax_query[] = array( 'taxonomy' => 'recipe_categories', 'field' => 'slug', 'terms' => $categories, 'operator' => 'IN' // 匹配选中分类中的任意一个 ); } // 仅当有筛选条件时设置查询参数 if (count($tax_query) > 1) { $query->set('tax_query', $tax_query); } } add_action('pre_get_posts', 'custom_recipe_filter_query'); // 注册查询变量,确保WordPress能识别筛选参数 function custom_recipe_query_vars($vars) { $vars[] = 'recipe_label'; $vars[] = 'recipe_categories'; return $vars; } add_filter('query_vars', 'custom_recipe_query_vars'); // 更新重写规则,支持友好URL function custom_recipe_rewrite_rule() { add_rewrite_rule('^recettes-easy/?', 'index.php?post_type=recipes', 'top'); // 单一标签友好URL add_rewrite_rule('^recettes-easy/label/([^/]+)/?', 'index.php?post_type=recipes&recipe_label=$matches[1]', 'top'); // 单一分类友好URL add_rewrite_rule('^recettes-easy/category/([^/]+)/?', 'index.php?post_type=recipes&recipe_categories=$matches[1]', 'top'); // 标签+分类组合友好URL(可选) add_rewrite_rule('^recettes-easy/label/([^/]+)/category/([^/]+)/?', 'index.php?post_type=recipes&recipe_label=$matches[1]&recipe_categories=$matches[2]', 'top'); } add_action('init', 'custom_recipe_rewrite_rule');
注意:修改重写规则后,必须到WordPress后台「设置-固定链接」页面点击「保存更改」刷新规则。
2. 整合筛选表单(支持多选提交)
将原有的两个独立表单合并为一个,优化字段命名以支持多选:
<div class="isFilterSection"> <div class="isSidebarTitle">Filtres</div> <form method="get" action="<?php echo esc_url(get_post_type_archive_link('recipes')); ?>" id="recipeFilterForm"> <!-- 标签筛选按钮组 --> <div class="categoryInputList"> <h4>Étiquettes</h4> <button type="button" class="isRecipeFilterBtn" data-term="fetes">Fêtes</button> <button type="button" class="isRecipeFilterBtn" data-term="facile">Facile</button> <button type="button" class="isRecipeFilterBtn" data-term="rapide">Rapide</button> <button type="button" class="isRecipeFilterBtn" data-term="epice">Épicé</button> <button type="button" class="isRecipeFilterBtn" data-term="vegetarien">Végétarien</button> <button type="button" class="isRecipeFilterBtn" data-term="sans-gluten">Sans gluten</button> <button type="button" class="isRecipeFilterBtn" data-term="sans-lactose">Sans lactose</button> <button type="button" class="isRecipeFilterBtn" data-term="sans-sucre">Sans sucre</button> <button type="button" class="isRecipeFilterBtn" data-term="cuisine-du-fenua">Cuisine du fenua</button> <button type="button" class="isRecipeFilterBtn" data-term="cuisine-du-monde">Cuisine du monde</button> <!-- 隐藏字段存储选中的标签 --> <input type="hidden" name="recipe_label" id="selectedLabels" value=""> </div> <!-- 分类复选框组 --> <div class="isCategoryCheckboxes"> <h4>Catégories</h4> <div class="categoryInputList"> <label for="snacking"> <input type="checkbox" name="recipe_categories[]" id="snacking" value="snacking"> Snacking </label> <label for="entree"> <input type="checkbox" name="recipe_categories[]" id="entree" value="entree"> Entrée </label> <label for="plat"> <input type="checkbox" name="recipe_categories[]" id="plat" value="plat"> Plat </label> <label for="dessert"> <input type="checkbox" name="recipe_categories[]" id="dessert" value="dessert"> Dessert </label> <label for="boissons"> <input type="checkbox" name="recipe_categories[]" id="boissons" value="boissons"> Boissons </label> </div> </div> <!-- 提交按钮 --> <button type="submit" class="filterSubmitBtn">Appliquer les filtres</button> </form> </div>
3. 修复JavaScript交互(管理选中状态+提交逻辑)
替换原有JS代码,实现选中状态记忆、多选项管理:
document.addEventListener('DOMContentLoaded', function() { const filterForm = document.getElementById('recipeFilterForm'); const labelButtons = document.querySelectorAll('.isRecipeFilterBtn'); const selectedLabelsInput = document.getElementById('selectedLabels'); const categoryCheckboxes = document.querySelectorAll('input[name="recipe_categories[]"]'); let selectedLabels = new Set(); // 从URL参数恢复选中状态 const urlParams = new URLSearchParams(window.location.search); const existingLabels = urlParams.getAll('recipe_label'); existingLabels.forEach(label => { selectedLabels.add(label); const btn = document.querySelector(`.isRecipeFilterBtn[data-term="${label}"]`); if (btn) btn.classList.add('active'); }); selectedLabelsInput.value = Array.from(selectedLabels).join(','); const existingCategories = urlParams.getAll('recipe_categories'); existingCategories.forEach(cat => { const checkbox = document.querySelector(`input[name="recipe_categories[]"][value="${cat}"]`); if (checkbox) checkbox.checked = true; }); // 标签按钮切换事件 labelButtons.forEach(btn => { btn.addEventListener('click', function() { const term = this.dataset.term; if (selectedLabels.has(term)) { selectedLabels.delete(term); this.classList.remove('active'); } else { selectedLabels.add(term); this.classList.add('active'); } selectedLabelsInput.value = Array.from(selectedLabels).join(','); }); }); // 表单提交处理 filterForm.addEventListener('submit', function(e) { // 清空旧的标签参数,重新添加选中项 urlParams.delete('recipe_label'); selectedLabels.forEach(label => urlParams.append('recipe_label', label)); // 更新表单提交URL this.action = `${get_post_type_archive_link('recipes')}?${urlParams.toString()}`; }); });
部署步骤
- 将PHP代码添加到子主题的
functions.php文件中 - 将表单代码替换原有筛选表单,插入到Divi页面的侧边栏或顶部区域
- 将JavaScript代码添加到子主题的
footer.php中,或通过Divi「主题选项-集成-添加到页脚」功能插入 - 到WordPress后台「设置-固定链接」页面点击「保存更改」刷新重写规则
内容的提问来源于stack exchange,提问作者Ezr4h
相关产品推荐
相关产品推荐

