[英]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_fabric
为name=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' );
我不确定这是否有任何潜在的副作用,所以如果有人有任何想法,请发表评论或让我知道!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.