我正在尝试创建一个 Woocommerce 过滤器。基本上一切正常,但存在一些动态问题。
<?php
// Functie om gefilterde termen binnen de context van de huidige categorie op te halen
function get_filtered_terms($taxonomy, $product_ids, $tax_query) {
if (empty($product_ids)) {
return array(); // Geen producten, geen termen
}
// Termen ophalen die zijn gekoppeld aan de huidige product-ID's
$terms = get_terms(array(
'taxonomy' => $taxonomy,
'object_ids' => $product_ids,
'hide_empty' => true,
));
// Termen specifiek binnen de huidige categorie context tellen
$filtered_terms = array();
foreach ($terms as $term) {
$term_count_query = new WP_Query(array(
'post_type' => 'product',
'posts_per_page' => -1,
'tax_query' => array_merge($tax_query, array(
array(
'taxonomy' => $taxonomy,
'field' => 'slug',
'terms' => $term->slug,
),
)),
'fields' => 'ids',
));
$term->count = $term_count_query->found_posts;
$filtered_terms[] = $term;
}
return $filtered_terms;
}
function custom_filter_form_shortcode() {
if (!is_product_category() && !is_tax('brand')) {
return ''; // Alleen de filter tonen op categorie- en merkspecifieke pagina's
}
ob_start();
// Huidige categorie of merk ophalen
$queried_object = get_queried_object();
// Filtervolgorde en zichtbaarheid van de instellingenpagina ophalen
$filter_order = get_option('filter_order_' . $queried_object->term_id, 'price,brand,size');
$filters_visibility = get_option('filters_visibility_' . $queried_object->term_id, array(
'price' => 1,
'brand' => 1,
'size' => 1
));
// Filtervolgorde verwerken
$filter_order = explode(',', $filter_order);
// Huidige product-ID's van de query ophalen (alle pagina's)
$tax_query = array(
'relation' => 'AND',
array(
'taxonomy' => $queried_object->taxonomy,
'field' => 'slug',
'terms' => $queried_object->slug,
),
);
// Merkenfilter toevoegen indien ingesteld
if (isset($_GET['brand'])) {
$tax_query[] = array(
'taxonomy' => 'brand',
'field' => 'slug',
'terms' => $_GET['brand'],
'operator' => 'IN'
);
}
// Maatfilter toevoegen indien ingesteld
if (isset($_GET['size'])) {
$tax_query[] = array(
'taxonomy' => 'pa_size',
'field' => 'slug',
'terms' => $_GET['size'],
'operator' => 'IN'
);
}
$total_product_ids = new WP_Query(array(
'post_type' => 'product',
'posts_per_page' => -1,
'tax_query' => $tax_query,
));
$product_ids = wp_list_pluck($total_product_ids->posts, 'ID');
// Filteren van de termen met de huidige filters
$brands = get_filtered_terms('brand', $product_ids, $tax_query);
// Render de filtervorm
?>
<div class="desktop-filter-container">
<form method="get" action="" class="custom-filter-form">
<div class="sort-dropdown">
<label for="orderby">Sorteren op:</label>
<select name="orderby" id="orderby" onchange="this.form.submit()">
<?php foreach ($orderby_options as $value => $label) : ?>
<option value="<?php echo esc_attr($value); ?>" <?php selected($selected_orderby, $value); ?>><?php echo esc_html($label); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="filter-section">
<h5>Prijs</h5>
<div class="price-slider-container">
</div>
<div id="price-range"></div>
</div>
<!-- Merk filter toevoegen -->
<?php
if (!empty($brands) && !is_wp_error($brands)) {
echo '<div class="attribute-section">';
echo '<h4 class="toggle-section" data-index="brand">Merk</h4>';
echo '<div class="attribute-terms">';
$term_count = 0;
foreach ($brands as $brand) {
$checked = isset($_GET['brand']) && is_array($_GET['brand']) && in_array($brand->slug, $_GET['brand']) ? 'checked' : '';
if ($term_count < 5) {
echo '<label class="checkbox-label">';
echo '<input type="checkbox" name="brand[]" value="' . esc_attr($brand->slug) . '" ' . $checked . '>';
echo esc_html($brand->name) . ' <span class="attribute-count">(' . $brand->count . ')</span>'; // Termnaam en aantal tonen
echo '</label>';
} else {
echo '<label class="checkbox-label more-terms" style="display:none;">';
echo '<input type="checkbox" name="brand[]" value="' . esc_attr($brand->slug) . '" ' . $checked . '>';
echo esc_html($brand->name) . ' <span class="attribute-count">(' . $brand->count . ')</span>'; // Termnaam en aantal tonen
echo '</label>';
}
$term_count++;
}
if ($term_count > 5) {
echo '<span class="show-more">Toon meer</span>';
}
echo '</div>';
echo '</div>';
}
?>
<?php
// Bestaande attributenfilters
$attributes = wc_get_attribute_taxonomies();
$count = 0;
foreach ($attributes as $attribute) {
$taxonomy = wc_attribute_taxonomy_name($attribute->attribute_name);
// Zichtbaarheid controleren voordat je weergeeft
if (isset($filters_visibility[$taxonomy]) && $filters_visibility[$taxonomy]) {
// Gefilterde termen ophalen met product_ids en huidige tax_query
$terms = get_filtered_terms($taxonomy, $product_ids, $tax_query);
if (!empty($terms) && !is_wp_error($terms)) {
echo '<div class="attribute-section">';
echo '<h4 class="toggle-section" data-index="' . $count . '">' . esc_html($attribute->attribute_label) . '</h4>';
echo '<div class="attribute-terms">';
$term_count = 0;
foreach ($terms as $term) {
$checked = isset($_GET[$taxonomy]) && is_array($_GET[$taxonomy]) && in_array($term->slug, $_GET[$taxonomy]) ? 'checked' : '';
if ($term_count < 5) {
echo '<label class="checkbox-label">';
echo '<input type="checkbox" name="' . esc_attr($taxonomy) . '[]" value="' . esc_attr($term->slug) . '" ' . $checked . '>';
echo esc_html($term->name) . ' <span class="attribute-count">(' . $term->count . ')</span>'; // Termnaam en aantal tonen
echo '</label>';
} else {
echo '<label class="checkbox-label more-terms" style="display:none;">';
echo '<input type="checkbox" name="' . esc_attr($taxonomy) . '[]" value="' . esc_attr($term->slug) . '" ' . $checked . '>';
echo esc_html($term->name) . ' <span class="attribute-count">(' . $term->count . ')</span>'; // Termnaam en aantal tonen
echo '</label>';
}
$term_count++;
}
if ($term_count > 5) {
echo '<span class="show-more">Toon meer</span>';
}
echo '</div>';
echo '</div>';
$count++;
}
}
}
?>
</form>
</div>
<div class="mobile-filter-container">
<button class="open-filters-btn">Filters</button>
<div class="mobile-filters">
<button class="close-filters-btn">×</button>
<form method="get" action="" class="custom-filter-form">
<div class="sort-dropdown">
<label for="orderby">Sorteren op:</label>
<select name="orderby" id="orderby" onchange="this.form.submit()">
<?php foreach ($orderby_options as $value => $label) : ?>
<option value="<?php echo esc_attr($value); ?>" <?php selected($selected_orderby, $value); ?>><?php echo esc_html($label); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="filter-section">
<h5>Prijs</h5>
<div class="price-slider-container">
</div>
<div id="price-range"></div>
</div>
<!-- Merk filter toevoegen -->
<?php
$brands = get_filtered_terms('brand', $product_ids, $tax_query);
if (!empty($brands) && !is_wp_error($brands)) {
echo '<div class="attribute-section">';
echo '<h4 class="toggle-section" data-index="brand">Merk</h4>';
echo '<div class="attribute-terms">';
$term_count = 0;
foreach ($brands as $brand) {
$checked = isset($_GET['brand']) && is_array($_GET['brand']) && in_array($brand->slug, $_GET['brand']) ? 'checked' : '';
if ($term_count < 5) {
echo '<label class="checkbox-label">';
echo '<input type="checkbox" name="brand[]" value="' . esc_attr($brand->slug) . '" ' . $checked . '>';
echo esc_html($brand->name) . ' <span class="attribute-count">(' . $brand->count . ')</span>'; // Termnaam en aantal tonen
echo '</label>';
} else {
echo '<label class="checkbox-label more-terms" style="display:none;">';
echo '<input type="checkbox" name="brand[]" value="' . esc_attr($brand->slug) . '" ' . $checked . '>';
echo esc_html($brand->name) . ' <span class="attribute-count">(' . $brand->count . ')</span>'; // Termnaam en aantal tonen
echo '</label>';
}
$term_count++;
}
if ($term_count > 5) {
echo '<span class="show-more">Toon meer</span>';
}
echo '</div>';
echo '</div>';
}
?>
<?php
// Bestaande attributenfilters
$attributes = wc_get_attribute_taxonomies();
$count = 0;
foreach ($attributes as $attribute) {
$taxonomy = wc_attribute_taxonomy_name($attribute->attribute_name);
// Zichtbaarheid controleren voordat je weergeeft
if (isset($filters_visibility[$taxonomy]) && $filters_visibility[$taxonomy]) {
// Gefilterde termen ophalen met product_ids en huidige tax_query
$terms = get_filtered_terms($taxonomy, $product_ids, $tax_query);
if (!empty($terms) && !is_wp_error($terms)) {
echo '<div class="attribute-section">';
echo '<h4 class="toggle-section" data-index="' . $count . '">' . esc_html($attribute->attribute_label) . '</h4>';
echo '<div class="attribute-terms">';
$term_count = 0;
foreach ($terms as $term) {
$checked = isset($_GET[$taxonomy]) && is_array($_GET[$taxonomy]) && in_array($term->slug, $_GET[$taxonomy]) ? 'checked' : '';
if ($term_count < 5) {
echo '<label class="checkbox-label">';
echo '<input type="checkbox" name="' . esc_attr($taxonomy) . '[]" value="' . esc_attr($term->slug) . '" ' . $checked . '>';
echo esc_html($term->name) . ' <span class="attribute-count">(' . $term->count . ')</span>'; // Termnaam en aantal tonen
echo '</label>';
} else {
echo '<label class="checkbox-label more-terms" style="display:none;">';
echo '<input type="checkbox" name="' . esc_attr($taxonomy) . '[]" value="' . esc_attr($term->slug) . '" ' . $checked . '>';
echo esc_html($term->name) . ' <span class="attribute-count">(' . $term->count . ')</span>'; // Termnaam en aantal tonen
echo '</label>';
}
$term_count++;
}
if ($term_count > 5) {
echo '<span class="show-more">Toon meer</span>';
}
echo '</div>';
echo '</div>';
$count++;
}
}
}
?>
<button type="submit" class="apply-filters-btn">Bevestig filters</button>
</form>
</div>
</div>
<script>
jQuery(document).ready(function($) {
function filterProducts() {
var selectedBrands = [];
var selectedSizes = [];
$('.checkbox-label input[name="brand[]"]:checked').each(function() {
selectedBrands.push($(this).val());
});
$('.checkbox-label input[name="size[]"]:checked').each(function() {
selectedSizes.push($(this).val());
});
$('.products .product').each(function() {
var product = $(this);
var productPrice = parseFloat(product.data('price'));
var productBrands = product.data('brands').split(',');
var productSizes = product.data('sizes').split(',');
var showProduct = true;
if (selectedBrands.length > 0 && !selectedBrands.some(r => productBrands.includes(r))) {
showProduct = false;
}
if (selectedSizes.length > 0 && !selectedSizes.some(r => productSizes.includes(r))) {
showProduct = false;
}
if (productPrice < minPrice || productPrice > maxPrice) {
showProduct = false;
}
if (showProduct) {
product.show();
} else {
product.hide();
}
});
}
// Automatically filter the products when a checkbox is clicked
$(document).on('change', '.checkbox-label input[type="checkbox"]', function() {
$(this).closest('form').submit();
});
// Submit form when user changes the input fields for min and max price
$('#min_price, #max_price').on('change keyup', function() {
$(this).closest('form').submit();
});
// Mobiele filter toggle
$('.open-filters-btn').on('click', function() {
$('.mobile-filters').addClass('active');
});
$('.close-filters-btn, .apply-filters-btn').on('click', function() {
$('.mobile-filters').removeClass('active');
});
// Initialize filtering
filterProducts();
});
</script>
<?php
return ob_get_clean(); // Zorg ervoor dat deze regel correct is afgesloten
}
add_shortcode('custom_filter_form', 'custom_filter_form_shortcode'); // Zorg ervoor dat deze regel correct is afgesloten
function apply_custom_filters($query) {
if (!is_admin() && $query->is_main_query() && (is_product_category() || is_shop() || is_tax('brand'))) {
// Huidige categorie of merk ophalen
$queried_object = get_queried_object();
$taxonomy = $queried_object->taxonomy;
$slug = $queried_object->slug;
// Filteren op attributen
$tax_query = array(
'relation' => 'AND',
array(
'taxonomy' => $taxonomy,
'field' => 'slug',
'terms' => $slug,
),
);
$attributes = wc_get_attribute_taxonomies();
foreach ($attributes as $attribute) {
$taxonomy_name = wc_attribute_taxonomy_name($attribute->attribute_name);
if (isset($_GET[$taxonomy_name])) {
$tax_query[] = array(
'taxonomy' => $taxonomy_name,
'field' => 'slug',
'terms' => $_GET[$taxonomy_name],
'operator' => 'IN'
);
}
}
// Filteren op merk
if (isset($_GET['brand'])) {
$tax_query[] = array(
'taxonomy' => 'brand',
'field' => 'slug',
'terms' => $_GET['brand'],
'operator' => 'IN'
);
}
// Stel het aantal producten per pagina in
$query->set('posts_per_page', 16);
}
}
add_action('pre_get_posts', 'apply_custom_filters');
function load_custom_scripts() {
wp_enqueue_script('jquery');
wp_enqueue_script('jquery-ui-slider');
wp_enqueue_style('jquery-ui-slider-css', '//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css');
}
add_action('wp_enqueue_scripts', 'load_custom_scripts');
function enqueue_sortable_script() {
wp_enqueue_script('jquery-ui-sortable');
wp_enqueue_script('custom-admin-script', get_template_directory_uri() . '/js/custom-admin.js', array('jquery', 'jquery-ui-sortable'), false, true);
}
add_action('admin_enqueue_scripts', 'enqueue_sortable_script');
add_action('admin_menu', 'custom_filters_menu');
function custom_filters_menu() {
add_submenu_page(
'edit.php?post_type=product',
'Filters',
'Filters',
'manage_options',
'custom-filters',
'custom_filters_page'
);
}
function custom_filters_page() {
// Get product categories
$categories = get_terms(array(
'taxonomy' => 'product_cat',
'hide_empty' => false,
));
?>
<div class="wrap">
<h1><?php _e('Product Filters Settings', 'textdomain'); ?></h1>
<form method="post" action="options.php">
<?php settings_fields('custom_filters_settings_group'); ?>
<?php do_settings_sections('custom_filters_settings_group'); ?>
<div class="form-table">
<?php foreach ($categories as $category) : ?>
<div class="category-section">
<h2><?php echo esc_html($category->name); ?></h2>
<div>
<?php
$filter_order = get_option('filter_order_' . $category->term_id, 'price,brand,size');
$filters_visibility = get_option('filters_visibility_' . $category->term_id, array(
'price' => 1,
'brand' => 1,
'size' => 1
));
// Ensure filters_visibility is an array
if (!is_array($filters_visibility)) {
$filters_visibility = array(
'price' => 1,
'brand' => 1,
'size' => 1
);
}
$attributes = wc_get_attribute_taxonomies();
?>
<ul class="sortable" id="sortable_<?php echo $category->term_id; ?>">
<?php foreach ($attributes as $attribute) :
$taxonomy = wc_attribute_taxonomy_name($attribute->attribute_name);
?>
<li id="<?php echo $taxonomy; ?>">
<label>
<input type="checkbox" name="filters_visibility_<?php echo $category->term_id; ?>[<?php echo $taxonomy; ?>]" value="1" <?php checked(isset($filters_visibility[$taxonomy]) ? $filters_visibility[$taxonomy] : 0, 1); ?> />
<?php echo esc_html($attribute->attribute_label); ?>
</label>
</li>
<?php endforeach; ?>
</ul>
<input type="hidden" class="filter-order-input" name="filter_order_<?php echo esc_attr($category->term_id); ?>" value="<?php echo esc_attr($filter_order); ?>" />
</div>
</div>
<?php endforeach; ?>
</div>
<?php submit_button(); ?>
</form>
</div>
<script>
jQuery(document).ready(function($) {
$('.sortable').sortable({
update: function(event, ui) {
var order = $(this).sortable('toArray').toString();
$(this).siblings('.filter-order-input').val(order);
}
});
$('.sortable').disableSelection();
});
</script>
<?php
}
add_action('admin_init', 'register_custom_filters_settings');
function register_custom_filters_settings() {
$categories = get_terms(array(
'taxonomy' => 'product_cat',
'hide_empty' => false,
));
foreach ($categories as $category) {
register_setting('custom_filters_settings_group', 'filter_order_' . $category->term_id);
register_setting('custom_filters_settings_group', 'filters_visibility_' . $category->term_id, array(
'type' => 'array',
'sanitize_callback' => 'custom_sanitize_filters_visibility'
));
}
}
function custom_sanitize_filters_visibility($input) {
$output = array();
foreach ($input as $key => $value) {
$output[$key] = intval($value);
}
return $output;
}
add_filter('woocommerce_product_query_tax_query', 'custom_product_query_tax_query', 10, 2);
function custom_product_query_tax_query($tax_query, $query) {
if (isset($_GET['pa_diagonaal-van-het-scherm-cm'])) {
$tax_query[] = array(
'taxonomy' => 'pa_diagonaal-van-het-scherm-cm',
'field' => 'slug',
'terms' => $_GET['pa_diagonaal-van-het-scherm-cm'],
'operator' => 'IN',
);
}
return $tax_query;
}
add_filter('woocommerce_layered_nav_counts', 'custom_layered_nav_counts', 10, 2);
function custom_layered_nav_counts($counts, $taxonomy) {
global $wpdb;
// Get the current category or brand
$queried_object = get_queried_object();
$current_term_id = $queried_object->term_id;
// Get the current filtered product IDs
$query = new WP_Query(array(
'post_type' => 'product',
'posts_per_page' => -1,
'post_status' => 'publish',
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => $queried_object->taxonomy,
'field' => 'term_id',
'terms' => $current_term_id,
),
WC()->query->get_main_tax_query(),
),
'meta_query' => WC()->query->get_meta_query(),
'fields' => 'ids'
));
$product_ids = $query->posts;
if (!empty($product_ids)) {
// Loop through each term in the taxonomy and count the products
foreach ($taxonomy->get_terms() as $term) {
$count = $wpdb->get_var($wpdb->prepare("
SELECT COUNT(DISTINCT p.ID)
FROM {$wpdb->posts} p
INNER JOIN {$wpdb->term_relationships} tr ON (p.ID = tr.object_id)
INNER JOIN {$wpdb->term_taxonomy} tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id)
WHERE p.post_type = 'product'
AND p.post_status = 'publish'
AND tt.taxonomy = %s
AND tt.term_id = %d
AND p.ID IN (" . implode(',', $product_ids) . ")
", $taxonomy->taxonomy, $term->term_id));
// Add the new count to the array
$counts[$term->term_id] = $count;
}
} else {
foreach ($taxonomy->get_terms() as $term) {
$counts[$term->term_id] = 0;
}
}
return $counts;
}
?>
您可以在这里测试: https://waaaauw.be/product-categorie/tv-video-en-thuisbioscoop-tv-s/
问题描述
正如你所看到的,当我为 example 106,7 cm (4) 选择时,它应该说“品牌”(这是一个分类法,而不是一个属性):
松下 (1)
LG (3)
A (2)
D (8)
E (109)
F (164)
G(202)
E (4) - 示例
当您按下“品牌”时,过滤器也会删除:
您可以在此
提供的链接上进行实时测试。
// Altijd de productcategorie ID ophalen (bijvoorbeeld via een URL-parameter of andere logica)
if (isset($_GET['product_cat'])) {
$current_product_cat_slug = sanitize_text_field($_GET['product_cat']);
$current_product_cat = get_term_by('slug', $current_product_cat_slug, 'product_cat');
if ($current_product_cat) {
$current_product_cat_id = $current_product_cat->term_id;
}
} else {
// Als er geen specifieke categorie is gekozen, gebruik dan de huidige term ID
$current_product_cat_id = $current_term_id;
}
// Debug log om de gebruikte productcategorie ID te controleren
error_log('Geselecteerde productcategorie ID: ' . $current_product_cat_id);
// Gebruik altijd de productcategorie ID om de zichtbaarheid van de attributenfilters op te halen
if ($current_product_cat_id) {
$filters_visibility = get_option('filters_visibility_' . $current_product_cat_id, array());
// Testwaarde toevoegen om te controleren of de optie correct wordt opgehaald
if (empty($filters_visibility)) {
// Voeg een testwaarde toe
$filters_visibility = array('pa_diagonaal-van-het-scherm-cm' => 1, 'pa_energieklasse' => 1);
update_option('filters_visibility_' . $current_product_cat_id, $filters_visibility);
error_log('Testwaarde ingesteld voor productcategorie ' . $current_product_cat_id);
}
error_log('Filters zichtbaarheid voor productcategorie ' . $current_product_cat_id . ': ' . print_r($filters_visibility, true));
} else {
$filters_visibility = array();
}
// Controleer of de filters_visibility een array is en niet leeg
if (is_array($filters_visibility) && !empty($filters_visibility)) {
error_log('Filters zichtbaarheid (eindresultaat): ' . print_r($filters_visibility, true));
} else {
error_log('Filters zichtbaarheid is leeg of geen array voor productcategorie ' . $current_product_cat_id);
$filters_visibility = array();
}
// Zorg ervoor dat de filters_visibility een array is
if (!is_array($filters_visibility)) {
$filters_visibility = array();
}
// Debug log om de definitieve filters zichtbaarheid te controleren
error_log('Definitieve filters zichtbaarheid: ' . print_r($filters_visibility, true));
此代码进行了更改:
// Testwaarde toevoegen om te controleren of de optie correct wordt opgehaald
if (empty($filters_visibility)) {
// Voeg een testwaarde toe
$filters_visibility = array('pa_diagonaal-van-het-scherm-cm' => 1, 'pa_energieklasse' => 1);
update_option('filters_visibility_' . $current_product_cat_id, $filters_visibility);
error_log('Testwaarde ingesteld voor productcategorie ' . $current_product_cat_id);
}