@easycode
не боюсь задавать глупые вопросы ))

Как организовать работу взаимозависимых фильтров товаров в WordPress-плагине?

Имеется простенький самописный WordPress-плагин Интернет-магазина.
Создана кастомная таксономия WordPress. Реализована фильтрация товаров:
5d19e34b4a2f9692197037.png
Характеристики по которым идет фильтрация записаны для товаров в мета-поля.
Соотв. получаем нужные товары в зависимости от выбранных фильтров так:
$args = array(
			'post_type' => 'product',
			'posts_per_page' => $data['page_count'] ? $data['page_count'] : 16,
			'post_status' => 'publish',
			'tax_query' => array(
		        array(
		            'taxonomy' => 'cats', 
		            'field' => 'term_id', 
		            'terms' => $_cat_id,
		        )
		    )
		);
		
		if (count($data['filters'])) {
			$args['meta_query'] = array(
				'relation' => 'OR',
			);
			foreach ($data['filters'] as $_filter => $_values) {
				$args['meta_query'][] = array(
					'key' => $_filter,
					'value' => (array) $_values,
				);
			}
		}
		$wp_query = new WP_Query( $args );

однако пока не приходит в голову как реализовать взимозависимую работу фильтров так, что если к примеру пользователь выбрал в фильтре: "Страна" определенное значение, то значения в остальных зависимых фильтрах изменились бы?

Вот например, выбрал пользователь в качестве страны - Беларусь, соотв. в фильтре: "Материал корпуса" должны остаться значения только для товаров из Беларуси, ну и соотв. т.д.

Пока в голову приходит только такой алгоритм:
  • берем список всех полученных в результате запроса товаров (а вернее их ID-шники)
  • выбираем все значения для каждого товара по каждой характеристике из таблицы: postmeta


но может есть более быстрое (оптимизированное) решение?
  • Вопрос задан
  • 359 просмотров
Пригласить эксперта
Ответы на вопрос 2
mihdan
@mihdan
WordPress-евангелист, ведущий РНР - разработчик
Рекомендую плагин фасетного поиска (фильтров) под названием FacetWP.
Ответ написан
@easycode Автор вопроса
не боюсь задавать глупые вопросы ))
Пока что обошелся ранее мною описанным подходом:

<?php

// $data - это массив передающийся в AJAX-запросе фильтрации товаров

// параметры основного запроса получения товаров для вывода на странице
$args = array(
	'post_type' => 'product',
	'posts_per_page' => $data['page_count'] ? $data['page_count'] : 16,
	'post_status' => 'publish',
	'tax_query' => array(
        array(
            'taxonomy' => 'cats', 
            'field' => 'term_id', 
            'terms' => $_cat_id,
        )
    )
);
// если пагинация
if ( is_numeric($data['page']) )  {
	$args['paged'] = (int) $data['page'];
}

$_filter_post_ids = array();

if (count($data['filters'])) { // если выбран хотя бы один фильтр
	$args['meta_query'] = array(
		'relation' => 'AND',
	);
	foreach ($data['filters'] as $_filter => $_values) {
		// собираем фильтрацию
		$args['meta_query'][] = array(
			'key' => $_filter,
			'value' => (array) $_values,
		);
	}

	// собираем ID всех товаров выбранных в результе фильтрации
	$args_filters = $args;
	$args_filters['posts_per_page'] = -1;
	$_posts = get_posts( $args_filters );
	if ( count($_posts) ) {
		foreach ($_posts as $_post) {
			$_filter_post_ids[] = $_post->ID;
		}
		$in = " AND `post_id` IN (" . implode(',', $_filter_post_ids) . ')';
	}

	// получаем массивы значений фильтров для вывода в интерфейсе фильтрации товаров
	foreach ($_filters_list as $_filter_name) {
		$_filter_values = $wpdb->get_results("SELECT `meta_value`, COUNT(meta_id) AS `counts` FROM `{$wpdb->prefix}postmeta` WHERE `meta_key` = '$_filter_name' AND `meta_value` != ''$in GROUP BY `meta_value`", ARRAY_A);
		if (count($_filter_values)) {
			foreach ($_filter_values as $_value) {
				$_filters_data[$_filter_name][$_value['meta_value']] = $_value['counts'];
			}
		}
	}
}

$wp_query = new WP_Query( $args );


Спорное решение - но работает и пока на небольшом кол-ве товаров в базе и кол-ве фильтров до 10 вроде не тормозит, посмотрим что будет дальше, возможно придется все переделывать иначе... но пока так...
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы