https://codex.wordpress.org/Class_Reference/WP_Query
https://codex.wordpress.org/Class_Reference/WP_Que...
UPDATE:
1. Создаем выпадающий список для фильтра со всеми уникальными значениями "брендов" (в соответствующем шаблоне - над Loop с постами, перед if( have_posts() ) ):
<?php
// Получаем все уникальные значения брендов
$brands = $wpdb->get_col(
"SELECT DISTINCT meta_value FROM $wpdb->postmeta WHERE meta_key = 'brand'"
);
// Если бренды есть - строим блок с фильтром
if ( $brands ) :
?>
<div class="filter">
<span>Filter by brand:</span>
<select name="brand" id="brand">
<!-- Сброс фильтра в значение "все" (оно же по умолчанию) -->
<option value="All"
<?php echo ( empty( $_GET['brand'] ) || 'All' === $_GET['brand'] ) ? 'selected="selected"' : ''; ?>
>All</option>
<!-- Все бренды -->
<?php foreach ( $brands as $brand ) : ?>
<option value="<?php echo esc_html( $brand ); ?>"
<?php echo ( ! empty( $_GET['brand'] ) && $brand === $_GET['brand'] ) ? 'selected="selected"' : ''; ?>
><?php echo esc_html( $brand ); ?></option>
<?php endforeach; ?>
</select>
</div>
<script>
jQuery('#brand').on('change', function(){
window.location.href = '<?php echo get_nopaging_url(); ?>' + '?brand=' + jQuery(this).val();
});
</script>
<?php endif; ?>
Конечно, этот кусочек javascript лучше перенести в свой файл скриптов, который подгружается через wp_enqueue_scripts(), данный пример для наглядности.
2. Хукаемся в основной запрос перед его выполнением, отлавливаем переменную и модифицируем запрос (это в functions.php):
/**
* Меняем основной запрос по необходимости, непосредственно перед его выполнением, сохраняя все фичи (включая пагинацию)
*/
function my_filter_posts( $query ) {
// Если это не главный запрос или админка - прекращаем выполнение
if( ! $query->is_main_query() || is_admin() ) {
return;
}
// Если есть GET-параметр brand с не пустым значением и оно не равно All - модифицируем запрос
if( ! empty( $_GET['brand'] ) && 'All' != $_GET['brand'] ) {
$query->set( 'meta_key', 'brand' );
$query->set( 'meta_value', sanitize_text_field( $_GET['brand'] ) );
}
}
add_action( 'pre_get_posts', 'my_filter_posts' );
3. И еще нам понадобится утилитарная функция get_nopaging_url() которую мы использовали в js (добавляем ее тоже в functions.php):
/**
* Get current URL without /page/{pagenum}/ part if it's present
*/
function get_nopaging_url() {
global $wp;
$current_url = home_url( $wp->request );
$position = strpos( $current_url , '/page' );
$nopaging_url = ( $position ) ? substr( $current_url, 0, $position ) : $current_url;
return trailingslashit( $nopaging_url );
}