Как создать фильтр постов на фронтенде с использованием мета-запроса

Вопрос или проблема

Я создал фильтр постов, как на изображении ниже, но у меня есть проблема с выбором нескольких значений из разных полей. Все поля в фильтре являются пользовательскими полями. Дело в том, что в админ-панели у одного поста есть поле выбора с городом Тель-Авив и поле выбора типа недвижимости с значением Садовая квартира. У другого поста другой город и тип недвижимости – Земляная квартира. На фронтенде, если я выбираю из поля Город -> Тель-Авив, я получаю один пост (квартиру), как и должно быть. Если я выбираю из поля Тип недвижимости -> Садовые и Земляные квартиры, не выбирая город, я получаю два результата, как и должно быть, но если я выбираю эти два типа квартир вместе с городом Тель-Авив, я должен получить только одну квартиру, но я все равно получаю два результата.

введите описание изображения здесь

Код: Вы можете заметить, что некоторые значения полей вызываются переменными, я просто вызывал эти поля ранее, но не добавил этот код здесь.

<form class="select_form advance" id = "filterformid" name="filterform" action="" method="get">
<fieldset>

<div id="stickySearch" style="background: transparent !important;">
  <div class="container">  

        <ul class="nav nav-tabs" data-tabs="tabs" id="search-tab" style="background: transparent !important;">           

<li id="city" class="" name="city">
    <h4 id="apartment_city"><?php echo $filter_city; ?> <span class="caret"></span></h4>
    <ul class="dropdown-list city"> 

        <?php $array_property = get_field_object($filter_city_field);

        $i=0;
        foreach ($array_property['choices'] as $key => $value) {
        $i++;
        if (in_array($key, $_GET['city'])) {

        echo '<li><input type="checkbox" id="city'. $i .'" class="uniquecity" name="city[]" value="'. $key .'" checked><label for="city'. $i .'">'.$value.'</label></li>';
        } else {
        echo '<li><input type="checkbox" id="city'. $i .'" class="uniquecity" name="city[]" value="'. $key .'"><label for="city'. $i .'">'.$value.'</label></li>';
        }
    }
        ?>
    </ul>            
</li>



                        <li id="beds" class="" name="rooms">
    <h4 id="bedrooms"><?php echo $filter_rooms; ?> <span class="caret"></span></h4>
    <ul class="dropdown-list beds"> 

        <?php $array_property = get_field_object('field_58ab19f3aef68');

        $i=0;
        foreach ($array_property['choices'] as $key => $value) {
        $i++;
        if($key == $_GET['rooms'] && !empty($_GET['rooms'])){
        echo '<li><input type="checkbox" id="bed'. $i .'" class="uniqueBed" name="rooms" value="'. $key .'" checked><label for="bed'. $i .'">'.$value.'</label></li>';
        } else {
        echo '<li><input type="checkbox" id="bed'. $i .'" class="uniqueBed" name="rooms" value="'. $key .'"><label for="bed'. $i .'">'.$value.'</label></li>';
        }
    }
        ?>
    </ul>            
</li>


<li id="floors" class="" name="floors">
    <h4 href="#" id="apartment_floors"><?php echo $filter_floors; ?> <span class="caret"></span></h4>
    <ul class="dropdown-list floors"> 

        <?php $array_property = get_field_object('field_58ab1a34aef69');
        $i=0;
        foreach ($array_property['choices'] as $key => $value) {
            $i++;
        if($key == $_GET['floors'] && !empty($_GET['floors'])){
        echo '<li><input type="checkbox" id="floors'. $i .'" class="uniquefloors" name="floors" value="'. $key .'" checked><label for="floors'. $i .'">'.$value.'</label></li>';
        } else {
        echo '<li><input type="checkbox" id="floors'. $i .'" class="uniquefloors" name="floors" value="'. $key .'"><label for="floors'. $i .'">'.$value.'</label></li>';
        }
    }
        ?>
    </ul>            
</li>



<li id="property_exposure" name="property">
    <h4 href="#" id="exposure"><?php echo $filter_exposure; ?> <span class="caret"></span></h4>
    <ul class="dropdown-list exposure"> 

    <?php 

    $array_property = get_field_object($filter_exposure_field);
    $i=0;
    foreach ($array_property['choices'] as $key => $value) {
    $i++;
    if (in_array($key, $_GET['property'])) {                                    
    echo '<li><input type="checkbox" id="exposure' . $i. '" class="uniqueexposure" name="property[]" value="'.$key.'" checked><label for="exposure'. $i .'">'.$value.'</label>';
    } else {
    echo '<li><input type="checkbox" id="exposure' . $i. '" class="uniqueexposure" name="property[]" value="'.$key.'"><label for="exposure'. $i .'">'.$value.'</label>';
    }   }
    ?>




    </ul>            
</li>

<li id="price">
  <h4 href="#"><?php echo $filter_price; ?> <span class="caret"></span></h4>
  <ul class="dropdown-list price">
    <li>

        <?php if($_GET['price_from'] != '0' && empty($_GET['price_from'])){ ?>
        <?php echo $filter_from; ?>
        <input placeholder="<?php echo $filter_min; ?>" type="text" name="price_from" id="min-price" value="">
        <?php } else { ?>
        <input placeholder="<?php echo $filter_min; ?>" type="text" name="price_from" id="min-price" value="<?php echo $_GET['price_from']; ?>">
        <?php } ?></li>
        <li>

      <?php echo $filter_to; ?> 

      <?php if(empty($_GET['price_to'])){ ?>
        <input placeholder="<?php echo $filter_max; ?>" type="text" name="price_to" id="max-price" value="">
        <?php } else { ?>
        <input placeholder="<?php echo $filter_max; ?>" type="text" name="price_to" id="max-price" value="<?php echo $_GET['price_to']; ?>">
        <?php } ?></li>



   </li>
  </ul>
</li>



<li id="property_type" class="" name="property_type">
    <h4 href="#" id="apartment_floors"><?php echo $filter_property_type; ?> <span class="caret"></span></h4>
    <ul class="dropdown-list property_type"> 

        <?php $array_property1 = get_field_object($filter_property_field);
        $i=0;

        foreach ($array_property1['choices'] as $key => $value) {
            $i++;


        if (in_array($key, $_GET['property_type'])) {
        echo '<li><input type="checkbox" id="property'. $i . '" class="uniqueproperty" name="property_type[]" value="'. $key .'" checked><label for="property'. $i .'">'.$value.'</label></li>';
        } else {
        echo '<li><input type="checkbox" id="property'. $i .'" class="uniqueproperty" name="property_type[]" value="'. $key .'"><label for="property'. $i .'">'.$value.'</label></li>';
        }
    }
        ?>
    </ul>            
</li>



<?php 
$array_includes = array(array(
                                'label' => 'Парковка',
                                'acf_name' => 'parking'
                                    )
                                    );
                                ?>


<li id="parking" class="" name="parking">


                                <?php foreach ($array_includes as $value) { ?>      
                                        <?php if( !empty($_GET['advance']) && in_array($value['acf_name'], $_GET['advance']) ) { ?>
                                        <h4 href="#" id="apartment_floors"><?php echo $filter_parking; ?> <input type="checkbox" checked id="<?php echo $value['acf_name'] ?>" name="advance[]" value="<?php echo $value['acf_name'] ?>"></h4>

                                        <?php } else { ?>
                                            <h4 href="#" id="apartment_floors"><?php echo $filter_parking; ?> <input type="checkbox" id="<?php echo $value['acf_name'] ?>" name="advance[]" value="<?php echo $value['acf_name'] ?>"></span></h4>
                                        <?php } ?> 


                                <?php } ?>
                                </li>






<li id="meters1">
  <h4 href="#"><?php echo $filter_meters; ?> <span class="caret"></span></h4>
  <ul class="dropdown-list meters">
    <li>
<?php echo $filter_from; ?>
        <?php if($_GET['meters_from'] != '0' && empty($_GET['meters_from'])){ ?>
                                    <input placeholder="<?php echo $filter_min; ?>" type="text" name="meters_from" id="min-meters" value="">
                                <?php } else { ?>
                                    <input placeholder="<?php echo $filter_min; ?>" type="text" name="meters_from" id="min-meters" value="<?php echo $_GET['meters_from']; ?>">
                                <?php } ?></li>
                                <li>

       <?php echo $filter_to;?>

      <?php if(empty($_GET['meters_to'])){ ?>
                                    <input placeholder="<?php echo $filter_max; ?>" type="text" name="meters_to" id="max-meters" value="">
                                <?php } else { ?>
                                    <input placeholder="<?php echo $filter_max; ?>" type="text" name="meters_to" id="max-meters" value="<?php echo $_GET['meters_to']; ?>" >
                                <?php } ?></li>



   </li>
  </ul>
</li>
<?php $queried_object_id = $wp_query->queried_object->term_id; ?>

<input type="hidden" name="termid" value="Residential Sale" />

<input type="submit" value="<?php echo $filter_search; ?>">
<div class="advance_block">
<?php $location =  $_GET['termid'];
        $args = array(
        'post_type'  => 'home_listings',
        'posts_per_page' => -1,
        'tax_query' => array(
            array(
                'taxonomy' => 'apartment_categories',
                'field'    => 'term_id',
                'terms'    => $queried_object_id
            ),
        ),
        'meta_query' => array(
            'relation' => 'AND'

        )

    );
    if(!empty($_GET['advance'])) {
        foreach($_GET['advance'] as $check) {
            $args['meta_query'][] = array(
                'key' => $check,
                'value' => '1',
                'compare' => 'LIKE'
            );
        }
    }
    foreach ($_GET['city'] as $city_single){
    if(!empty($_GET['city']) && $_GET['city'] != 'all') {
        $args['meta_query'][] = array(
            'key' => 'city',
            'value' => $city_single,
            'compare' => 'LIKE'
        );
    }
}
    if(!empty($_GET['neighborhood']) && $_GET['neighborhood'] != 'all') {
        $args['meta_query'][] = array(
            'key' => 'select_neighbourhood',
            'value' => $_GET['neighborhood'],
            'compare' => 'LIKE'
        );
    }
    if ( !empty($_GET['price_from']) || !empty($_GET['price_to']) ) {
        if($_GET['price_from'] != 'all'){
            $from = (int)$_GET['price_from'];
        } else {
            $from = 0;
        }
        if($_GET['price_to'] != 'all'){
            $to = (int)$_GET['price_to'];
        } else {
            $to = 0;
        }
            $args['meta_query'][] = array(
            'key' => 'price',
            'value' => array($from,$to),
            'type' => 'numeric',
            'compare' => 'BETWEEN'
        );
    }
    if ( !empty($_GET['meters_from']) || !empty($_GET['meters_to']) ) {
        if($_GET['meters_from'] != 'all'){
            $from = (int)$_GET['meters_from'];
        } else {
            $from = 0;
        }
        if($_GET['meters_to'] != 'all'){
            $to = (int)$_GET['meters_to'];
        } else {
            $to = 0;
        }
        $args['meta_query'][] = array(
            'key' => 'square_feet',
            'value' => array($from,$to),
            'type' => 'numeric',
            'compare' => 'BETWEEN'
        );
    }
    foreach ($_GET['property'] as $exposure_single){
    if(!empty($_GET['property']) && $_GET['property'] != 'all') {
        $args['meta_query'][] = array(
            'key' => 'exposure',
            'value' => $exposure_single,
            'compare' => 'LIKE'
        );
    }
}

        foreach ($_GET['property_type'] as $property_single){
            if(!empty($_GET['property_type']) && $_GET['property_type'] != 'all') {
        $args['meta_query'][] = array(
            'key' => 'property_type',
            'value' => $property_single,
            'compare' => 'LIKE'
        );
        }
    }

    if(!empty($_GET['rooms']) && $_GET['rooms'] != 'all') {
        $args['meta_query'][] = array(
            'key' => 'number_of_rooms',
            'value' => $_GET['rooms'],
            'compare' => 'LIKE'
        );
    }
    if(!empty($_GET['floors']) && $_GET['floors'] != 'all') {
        $args['meta_query'][] = array(
            'key' => 'floors',
            'value' => $_GET['floors'],
            'compare' => 'LIKE'
        );
    }
    // Сохранить переменные строки запроса
    foreach ( $_GET as $key => $value ) {

        if ( 
            'rooms' === $key || 
            'floors' === $key || 
            'property_type' === $key ||
            'submit' === $key || 
            'advance' === $key ||
            'city' === $key ||
            'neighborhood' === $key ||
            'property' === $key ||
            'price_from' === $key ||
            'price_to' === $key ||
            'meters_from' === $key ||
            'meters_to' === $key
        ) {
            continue;
        }
        if ( is_array( $val ) ) {
            foreach( $val as $innerVal ) {
                echo '<input type="hidden" name="' . esc_attr( $key ) . '[]" value="' . esc_attr( $innerVal ) . '" />';

            }
        } else {
            echo '<input type="hidden" name="' . esc_attr( $key ) . '" value="' . esc_attr( $val ) . '" />';
        }
    }
    $wp_qunew WP_Query($args);
                                ?>

Пожалуйста, перейдите по этой ссылке

https://aftabablog.wordpress.com/2016/06/16/how-to-create-a-custom-filter-in-wp/

Надеюсь, это даст вам представление о том, как создать пользовательский фильтр на основе мета-запроса

  1. Исправьте опечатку: строка $wp_qunew WP_Query($args); похоже, является опечаткой. Это должно быть $wp_query = new WP_Query($args);.
  2. Исправьте переменные: в цикле foreach в конце кода вы перебираете переменные $_GET, но используете $val вместо $value. Также вы должны проверить, является ли $value массивом, и обработать его соответствующим образом.

Проверьте этот код еще раз
foreach ( $_GET as $key => $value ) {

if ( 
    'rooms' === $key || 
    'floors' === $key || 
    'property_type' === $key ||
    'submit' === $key || 
    'advance' === $key ||
    'city' === $key ||
    'neighborhood' === $key ||
    'property' === $key ||
    'price_from' === $key ||
    'price_to' === $key ||
    'meters_from' === $key ||
    'meters_to' === $key
) {
    continue;
}
if ( is_array( $value ) ) {
    foreach( $value as $innerVal ) {
        echo '<input type="hidden" name="' . esc_attr( $key ) . '[]" value="' . esc_attr( $innerVal ) . '" />';
    }
} else {
    echo '<input type="hidden" name="' . esc_attr( $key ) . '" value="' . esc_attr( $value ) . '" />';
}

}
$wp_query = new WP_Query($args);

Пожалуйста, выполните эти два шага, чтобы решить этот вопрос

Ответ или решение

Чтобы создать передний фильтр для постов с использованием meta query в WordPress, вам необходимо правильно реализовать логику фильтрации, которая будет учитывать множественные значения из различных полей. Исходя из вашего описания, вам нужно убедиться, что выбранные значения из полей фильтра взаимодействуют правильно.

Решение вашей проблемы

  1. Структура Meta Query:
    Основная проблема, которую вы описали, заключается в том, что даже при выборе нескольких значений из разных полей, фильтрация не работает так, как ожидалось. Вам необходимо использовать relation в вашем meta_query, чтобы объединить условия для фильтрации. Например, если вы выбираете город и тип недвижимости, вы хотите убедиться, что оба условия выполняются одновременно.

  2. Исправление кода:
    Ваша текущая реализация meta_query не учитывает совместные условия должным образом. Вы можете использовать relation => 'AND', чтобы убедиться, что соответствие происходит для обоих полей (например, город и тип недвижимости).

    Ниже приведен пример изменения вашего кода для достижения желаемого поведения:

$args = array(
    'post_type' => 'home_listings',
    'posts_per_page' => -1,
    'tax_query' => array(
        array(
            'taxonomy' => 'apartment_categories',
            'field'    => 'term_id',
            'terms'    => $queried_object_id
        ),
    ),
    'meta_query' => array('relation' => 'AND')  // устанавливаем отношение AND
);

// Добавляем фильтрацию для города
if (!empty($_GET['city'])) {
    $city_queries = array();
    foreach ($_GET['city'] as $city_single) {
        $city_queries[] = array(
            'key' => 'city',
            'value' => $city_single,
            'compare' => 'LIKE'
        );
    }
    $args['meta_query'][] = array(
        'relation' => 'OR', // Используем OR здесь для обработки множества городов
        $city_queries
    );
}

// Правильное добавление других полей
if (!empty($_GET['property_type'])) {
    foreach ($_GET['property_type'] as $property_single) {
        $args['meta_query'][] = array(
            'key' => 'property_type',
            'value' => $property_single,
            'compare' => 'LIKE'
        );
    }
}

// Добавьте аналогичный код для других полей фильтрации, например 'floors', 'rooms', и т.д.
  1. Использование WP_Query:
    Убедитесь, что вы корректно создаете объект класса WP_Query в конце вашего запроса:
$wp_query = new WP_Query($args);
  1. Проверка и обработка значений:
    Ваша обработка значений должна быть корректной. Убедитесь, что вы проверяете, является ли значение массивом и обрабатываете его соответственно:
foreach ($_GET as $key => $value) {
    if (is_array($value)) {
        foreach ($value as $innerVal) {
            echo '<input type="hidden" name="' . esc_attr($key) . '[]" value="' . esc_attr($innerVal) . '" />';
        }
    } else {
        echo '<input type="hidden" name="' . esc_attr($key) . '" value="' . esc_attr($value) . '" />';
    }
}

Заключение

Убедившись, что meta_query правильно настроен с использованием условия AND и OR для различных массивов значений, и что WP_Query вызван корректно, вы сможете достичь желаемого результата с фильтрацией. Обязательно протестируйте фильтр, чтобы убедиться, что он работает на уровне, который вам необходим.

Если у вас есть дальнейшие вопросы или требуется дополнительная помощь, пожалуйста, дайте знать!

Оцените материал
Добавить комментарий

Капча загружается...