You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()}`;
    });
});

部署步骤

  1. 将PHP代码添加到子主题的functions.php文件中
  2. 将表单代码替换原有筛选表单,插入到Divi页面的侧边栏或顶部区域
  3. 将JavaScript代码添加到子主题的footer.php中,或通过Divi「主题选项-集成-添加到页脚」功能插入
  4. 到WordPress后台「设置-固定链接」页面点击「保存更改」刷新重写规则

内容的提问来源于stack exchange,提问作者Ezr4h

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 12:58:11