繁体   English   中英

将多个值添加到 WordPress 中的查询变量

[英]Adding multiple values to a query variable in WordPress

提示:本站为国内最大中英文翻译问答网站,提供中英文对照查看,鼠标放在中文字句上可显示英文原文

我偶然发现了一个问题,我在 Wordpress 中注册了一个自定义查询变量。但是,我想用相同的自定义查询传递几个值并将其返回到一个数组中,但它重定向/只考虑最后一个查询值。

我这样做了:

function custom_query_vars( $qvars ) {
    $qvars[] = 'filter_fabric';
    return $qvars;
}
add_filter( 'query_vars', 'custom_query_vars' );

但是,如果我像这样传递 url:

example.com/category/page/2?filter_fabric=cotton&filter_fabric=polyester

我可以在 $query 中看到只传递了最后一个参数,在本例中为“polyester”,这会导致分页错误(当我单击地址为example.com/category/page/2?filter_fabric=cotton&filter_fabric=polyester它将我重定向到example.com/category/page/2?filter_fabric=polyester

有谁知道如何解决这个问题? 会有很大的帮助!

我也尝试添加此代码,但没有成功:

function custom_query_vars( $qvars ) {
    $qvars[] .= 'filter_fabric';
    return $qvars;
}
add_filter( 'query_vars', 'custom_query_vars' );

我假设它与 foreach 循环有关,它作为数组推入 $qvars[],但我不确定该怎么做。

编辑#1

这是我使用 ajax 进行过滤的代码。

functions.php中.php

function rg_product_filter() {

//unserialize query string in PHP
//parse_str($_POST['value'], $data); We change this to our custom proper_parse_str function in order to get multiple parameters with same name e.g. "/?filter_tygmaterial=sammet&filter_tygmaterial=bomull"
$data = proper_parse_str($_POST['value']);

$product_color = $data['filter_color'];
$product_material = $data['filter_material'];
$product_fabric = $data['filter_fabric'];
$wpquery_vars = $_POST['query_vars'];

//Get current product category id
$product_category = $wpquery_vars['queried_object'];
$product_cat_id = $product_category['term_id'];

//Get current order + orderby if exists, part 2
$args_orderby = $data['filter_orderby'];

//@TODO: Right now it does not work with pagination. 
$per_page = $_POST['per_page'];
$current = $_POST['current'];

$args = array(
    'post_type' => 'product',
    'posts_per_page' => $per_page,
    'paged' => $current,
);
if ($args_orderby) {
    if ($args_orderby === 'price') {
        $args['orderby'] = 'meta_value_num';
        $args['order'] = 'asc';
        $args['meta_key'] = '_price';
    } elseif ($args_orderby === 'price-desc') {
        $args['orderby'] = 'meta_value_num';
        $args['order'] = 'desc';
        $args['meta_key'] = '_price';
    } else {
        $args['orderby'] = $args_orderby;
    }
}
if ($product_category) {
    $args['tax_query'][] = array(
            'taxonomy' => 'product_cat',
            'field' => 'term_id',
            'terms' => $product_cat_id,
    );
}
if ($product_color) {
    $args['tax_query'][] = array(
        'taxonomy' => 'pa_color',
        'field' => 'slug',
        'terms' => $product_color,
    );
}
if ($product_material) {
    $args['tax_query'][] = array(
        'taxonomy' => 'pa_material',
        'field' => 'slug',
        'terms' => $product_material,
    );
}
if ($product_fabric) {
    $args['tax_query'][] = array(
        'taxonomy' => 'pa_tygmaterial',
        'field' => 'slug',
        'terms' => $product_fabric,
    );
}

$loop = new WP_Query( $args );

if ( $loop->have_posts() ) {
    while ( $loop->have_posts() ) : $loop->the_post();
        wc_get_template_part( 'content', 'product' );
    endwhile;
} else {
    do_action( 'woocommerce_no_products_found' );
}

wp_reset_postdata();

wp_die();
}
add_action('wp_ajax_rg_product_filter', 'rg_product_filter');
add_action('wp_ajax_nopriv_rg_product_filter', 'rg_product_filter');

customjs.js

    //WooCommerce Filters using AJAX
window.addEventListener("load", (event) => {
    
    $filterForm = $('#filter-form') ? $('#filter-form') : '';
    $filterForm.on('submit', function (e) {
        e.preventDefault();

        var values = $(this).serialize();
        var product_container = $('.woocommerce ul.products');

        // console.log('values', values);

        //append browser URL with filters
        let url = window.location.href;
        let filterParams = values.replace(/[^&]+=&/g, '').replace(/&[^&]+=$/g, '') //remove empty values from URL
        let baseUrl = url.includes('?') ? url.split('?')[0] : '',
            paramsInUrl = url.includes('?') ? url.split(('?'))[1] : '',
            paramsInUrlWithoutFilter = paramsInUrl.startsWith('filter') ? '' : paramsInUrl.split('&filter')[0]; //Get all params that are before "filter" if exists any 
        if (filterParams.endsWith('=') && paramsInUrlWithoutFilter) { //Removing from URL when exists other parameters than filter
            filterParams = '';
            url_with_filters = '?' + paramsInUrlWithoutFilter;
            window.history.pushState(null, null, url_with_filters);
        } else if (filterParams.endsWith('=') && !paramsInUrlWithoutFilter) { //Removing from URL when no other parameteres except filter exists
            filterParams = '';
            url_with_filters = location.pathname;
            window.history.pushState(null, null, url_with_filters);
        } else if (paramsInUrlWithoutFilter) { //Appending to browser URL when exists other parameters than filter
            filterParams = filterParams;
            url_with_filters = '?' + paramsInUrlWithoutFilter + '&' + filterParams;
            window.history.pushState(null, null, url_with_filters);
        } else { //Appending to browser URL when no other parameters except filter exists
            filterParams = filterParams;
            url_with_filters = '?' + filterParams;
            window.history.pushState(null, null, url_with_filters);
        }

        //Update product results text
        var resultCountElement = $('.title-wrapper .woocommerce-result-count.rg_woocommerce-total-count');
        
        // Add loader
        product_container.block({
            message: null,
            overlayCSS: {
                cursor: 'none',
                backgroundColor: '#fff',
            },
        });

        $.ajax({
            url: wp_ajax.ajax_url,
            method: 'POST',
            data: {
                value: values,
                action: 'rg_product_filter',
                per_page: wp_ajax.per_page,
                current: wp_ajax.current,
                query_vars: wp_ajax.wp_query_vars,
            },
            success: (res) => {
                // console.log(res);
                $('.woocommerce ul.products').html(res);
                product_container.unblock();

                //Update product results text
                resultCount = $('ul.products li.product').length;
                resultCountElement.html(resultCount + ' produkter');
            },
            error: (res) => {
                console.log(res);
            }

        });

    });

    //Select forms (not e.g. input groups)
    $('select.form-control').each( function () {
        $(this).on('change', $(this), (e) => {
            if (e.handled !== true) { //Adding this if statement, because otherwise code $filterForm.submit(); is fired several times
                e.handled = true;
                $('.wc-filter .sorting__submit').css('display', 'block');
                return;
            }
          });
    });

    //Input groups
    $('.input-group').each( function () {
        $(this).on('change', ':checkbox', (e) => {
            $('.wc-filter .sorting__submit').css('display', 'block');
        });
    });

    // Orderby
    $( '.input-group' ).on( 'change', 'input[type="radio"]', function() {
        $('.wc-filter .sorting__submit').css('display', 'block');
    });
    $('.wc-filter').on('click', '.sorting__submit', function () {
        $filterForm.submit();
        var filterOverlay = document.getElementsByClassName('product-filters-bg-overlay')[0] ? document.getElementsByClassName('product-filters-bg-overlay')[0] : '';
        var filterContainer = document.getElementsByClassName('wc-filter')[0] ? document.getElementsByClassName('wc-filter')[0] : '';
        filterOverlay.classList.toggle('toggled');
        filterContainer.classList.toggle('toggled');
        $('body.woocommerce').css('overflow', '');

    });
    

最后,我有filters.php : Ps:请注意,我已根据建议将输入组的名称从name=filter_fabricname=filter_fabric[]

    <?php

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

$color_terms = get_terms('pa_color');
$material_terms = get_terms('pa_material');
$fabric_terms = get_terms(
    array(
        'taxonomy' => 'pa_tygmaterial',
    ));

?>
<div class="product-filters__panelbody">
    
    <form id="filter-form" method="get" action="rg_product_filter">
        <div class="product-filters-wrapper">
        <?php /* Order By */ ?>
            <div class="product-filters-item catalog-ordering">
                <div class="product-filters-item-heading collapse-button" 
                data-toggle="collapse" 
                data-target="#tab_filter-sorting" 
                aria-expanded="false" 
                aria-controls="#tab_filter-sorting"
                >Sortering
                <svg viewBox="0 0 24 24" class="icon__product-filters-item">
                    <path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
                </svg>
                </div>
                <div class="collapse-body collapse-element collapse"
                    id="tab_filter-sorting"
                    >
                    <div class="product-filters-item-content">
                        <?php echo woocommerce_catalog_ordering(); ?>
                    </div>
                </div>
            </div>
            <?php /* Color */ ?>
            <div class="product-filters-item">
                <div class="product-filters-item-heading collapse-button" 
                data-toggle="collapse" 
                data-target="#tab_filter-color" 
                aria-expanded="false" 
                aria-controls="#tab_filter-color"
                >Color
                <svg viewBox="0 0 24 24" class="icon__product-filters-item">
                    <path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
                </svg>
                </div>
                <div class="collapse-body collapse-element collapse"
                    id="tab_filter-color"
                    >
                    <div class="product-filters-item-content">
                        <select name="filter_color" id="filter_color" class="form-control">
                            <option value="" class="">Color</option>
                            <?php foreach ($color_terms as $color_term) {

                                $selected = $color_term->slug === $_GET['filter_color'] ? 'selected' : '';
                                echo '<option ' . $selected . ' value="' . $color_term->slug . '">' . $color_term->name . '</option>';
                            }?>
                        </select>
                    </div>
                </div>
            </div>
            <?php /* Material */ ?>
            <div class="product-filters-item">
                <div class="product-filters-item-heading collapse-button"
                data-toggle="collapse" 
                data-target="#tab_filter-material" 
                aria-expanded="false" 
                aria-controls="#tab_filter-material"
                >Material
                <svg viewBox="0 0 24 24" class="icon__product-filters-item">
                    <path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
                </svg>
                </div>
                <div class="collapse-body collapse-element collapse"
                    id="tab_filter-material">
                    <div class="product-filters-item-content">
                        <select name="filter_material" id="filter_material" class="form-control">
                            <option value="" class="">Material</option>
                            <?php foreach ($material_terms as $material_term) {

                                $selected = $material_term->slug === $_GET['filter_material'] ? 'selected' : '';
                                echo '<option ' . $selected . ' value="' . $material_term->slug . '">' . $material_term->name . '</option>';
                            }?>
                        </select>
                    </div>
                </div>
            </div>
            <?php /* Fabrics */ ?>
            <div class="product-filters-item">
                <div class="product-filters-item-heading collapse-button"
                data-toggle="collapse" 
                data-target="#tab_filter-fabrics" 
                aria-expanded="false" 
                aria-controls="#tab_filter-fabrics"
                >Fabrics
                <svg viewBox="0 0 24 24" class="icon__product-filters-item">
                    <path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
                </svg>
                </div>
                <div class="collapse-body collapse-element collapse"
                    id="tab_filter-fabrics">
                    <div class="product-filters-item-content">
                        <?php foreach ($fabric_terms as $fabric_term) {

                            //Get parameters from URL
                            $url_parameters = $_SERVER['QUERY_STRING'];
                            $data = proper_parse_str($url_parameters);
                            $product_fabrics = $data['filter_fabric'];

                            //Check if filter input is in array of parameters from URL, and mark the input as "checked"
                            if (isset($product_fabrics)) {

                                if (is_array($product_fabrics)) { //If more than one parameter is checked, $product_tygmaterial becomes array
                                    $checked = in_array($fabric_term->slug, $product_fabrics) ? 'checked' : '';
                                } else { //If only one parameter is checked, $product_tygmaterial becomes string
                                    $checked = $fabric_term->slug === $product_fabrics ? 'checked' : '';
                                }

                            } else {
                                $checked = '';
                            }

                            ?>
                            <div class="input-group">
                                <input type="checkbox" id="<?php echo $fabric_term->slug; ?>" name="filter_fabric[]" value="<?php echo $fabric_term->slug ?>" <?php echo $checked; ?>>
                                <label for="<?php echo $fabric_term->slug; ?>"><?php echo $fabric_term->name; ?></label>
                            </div>
                        <?php }
                    ?>
                    </div>
                </div>
            </div>
        </div>
    </form>
</div>
<?php /* Submit Button for Product Sorting */?>
<div class="submit__button-wrapper">
    <button style="display: none;" class="sorting__submit">Show products</button>
</div>
<?php

请让我知道这是否有意义,我知道 filters.php 中有很多代码,但重要的部分是用“Fabrics”标注的部分,因为这是我遇到问题的输入组。

编辑#2我意识到我的functions.php文件中可能有一个重要的 function 需要提及。

如果参数位于 URL 中的“干净/美丽”state(即example.com/category/page/2?filter_fabric=cotton&filter_fabric=polyester )中,则此方法工作正常,但是当我在分页链接上时,它会自动重定向到example.com/category/page/2?filter_fabric=polyester 它在页面加载之前执行此操作,正如我在我的开发工具中看到的那样,一个 301 请求仅使用最后一个参数发送到第二个 url。 我假设这是一些 Wordpress 自动 function 这样做的 - 有什么办法可以禁用它吗?

function _url_parameters_query( $query ) {

//Check if query is for archive pages (otherwise this breaks e.g. nav header WP_Query)
if ($query->query_vars['wc_query'] !== 'product_query' || is_admin() ) {
    return;
}

$url_parameters = $_SERVER['QUERY_STRING'];
$data = proper_parse_str($url_parameters);
$product_fabric = $data['filter_fabric'] ? $data['filter_fabric'] : null;


//Check if filter input is in array of parameters from URL, and mark the input as "checked"
if (isset($product_fabric)) {

    // you can't use the query->set here for tax_query as tax query has already been made so you need to need add the data to any existing tax query
    $tax_query = array(
        'taxonomy' => 'pa_tygmaterial',
        'field' => 'slug',
        'terms' => $product_fabric,
        'relation' => 'AND',
    );
    $query->tax_query->queries[] = $tax_query; 
    $query->query_vars['tax_query'] = $query->tax_query->queries;
    if (array_key_exists('filter_fabric', $query->query)) {
        // echo 'hello there Renjo!';
        $query->query['filter_fabric'] = $product_fabric;
    }
}
}
add_action( 'pre_get_posts', '_url_parameters_query' );

我想我通过在functions.php中添加以下 function 解决了这个问题。 我意识到是重定向给我带来了问题,所以我添加了以下内容:

//Remove redirection when filters with same name are set in URL (i.e. filters from input_groups), otherwise only passes last value
# e.g. example.com/category/page/2/?filter_fabric=cotton&filter_fabric=polyester => example.com/category/page/2/?filter_fabric=polyester
function _disable_redirect_query_params() {
    global $wp_query;
    if ($wp_query->query_vars['wc_query'] !== 'product_query' || is_admin() ) {
        return;
    }

    if (isset($_GET['filter_tygmaterial']) ) {
       remove_action('template_redirect', 'redirect_canonical');
    }
}
add_action( 'wp', '_disable_redirect_query_params' );

我不确定这是否有任何潜在的副作用,所以如果有人有任何想法,请发表评论或让我知道!

问题未解决?试试搜索: 将多个值添加到 WordPress 中的查询变量
暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2023 STACKOOM.COM