Фильтрация результатов произвольного типа записи с использованием meta_query и ACF

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

Я использую пользовательский тип записи с названием property, чтобы перечислить несколько домов и квартир. В этом CPT у меня есть несколько пользовательских полей от плагина Advanced Custom Fields, таких как localization, price, rooms и так далее. Это HTML-форма, которую я использую для фильтрации результатов с использованием метода GET

<form>
  <button type="submit">фильтр</button>
  
  <select name="orderby" id="">
    <option value="" disabled selected>Сортировать по:</option>
    <option value="all">Все</option>
    <option value="ASC">Низкая цена</option>
    <option value="DESC">Высокая цена</option>
  </select>

  <h3>Тип контракта</h3>
  <select name="contract">
    <option value="" selected disabled>Выберите опцию</option>
    <option value="rent">Аренда</option>
    <option value="for_sale">На продажу</option>
  </select>
  ...
</form>

В моем цикле у меня есть этот массив, основанный на Codex. Я использую пример вложенных массивов, он не сработал.

<?php 
  $args = array(
    'post_type' => 'property',
    'posts_per_page' => -1,
    'meta_key' => 'price',
    'orderby' => 'meta_value_num',
    'order' => $_GET['orderby'],
    'meta_query' => array(
       'relation' => 'AND',
           array(
              array(
                 'key'   => 'contract',
                 'value' => $_GET['contract'],
                 'compare' => '='
              ),
          array(
                 'key'   => 'rooms',
                 'value' => $_GET['rooms'],
                 'compare' => '='
          ),
          ...
          $query = new WP_Query($args);
             if($query->have_posts()) : while($query->have_posts()) : $query->the_post()
          ...

Итак, для списка CPT на основе этой формы в качестве фильтра с использованием параметров GET, а также для сортировки по цене по ASC или DESC, что мне следует сделать?

Для meta_query с ACF и сортировки цены по ASC или DESC попробуйте следующий код.

$args = array(
  'post_type' => 'property',
  'posts_per_page' => -1,
  'meta_key' => 'price',
  'orderby' => 'meta_value_num',
  'order' => $_GET['orderby'],
  'meta_query' => array(
      'relation' => 'AND',
      array(
        'key'   => 'contract',
        'value' => $_GET['contract'],
      ),
      array(
        'key'   => 'rooms',
        'value' => $_GET['rooms'],
      ),
      ...
   ),
);
$query = new WP_Query($args);
if($query->have_posts()) : 
   while($query->have_posts()) : $query->the_post();
      // ваш код 
   endwhile;
endif;

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

Для фильтрации результатов пользовательского типа записи (Custom Post Type) с использованием meta_query и плагина Advanced Custom Fields (ACF), вы можете следовать приведённому ниже коду. В этом примере предполагается, что у вас есть форма, которая отправляет данные с методом GET, и вы хотите получить результаты на основе выбранных параметров, таких как контракт, количество комнат и порядок сортировки по цене.

  1. HTML форма для фильтрации:
<form method="GET">
  <button type="submit">Фильтр</button>

  <select name="orderby">
    <option value="" disabled selected>Сортировать по:</option>
    <option value="ASC">Низшая цена</option>
    <option value="DESC">Высшая цена</option>
  </select>

  <h3>Тип контракта</h3>
  <select name="contract">
    <option value="" selected disabled>Выберите опцию</option>
    <option value="rent">Аренда</option>
    <option value="for_sale">Продажа</option>
  </select>

  <h3>Количество комнат</h3>
  <select name="rooms">
    <option value="" selected disabled>Выберите количество</option>
    <option value="1">1 комната</option>
    <option value="2">2 комнаты</option>
    <option value="3">3 комнаты</option>
    <!-- Добавьте дополнительные опции при необходимости -->
  </select>
</form>
  1. Код для запроса на основе фильтров:
<?php 
$args = array(
  'post_type' => 'property',
  'posts_per_page' => -1,
  'meta_key' => 'price',
  'orderby' => 'meta_value_num',
  'order' => isset($_GET['orderby']) ? $_GET['orderby'] : 'ASC',
  'meta_query' => array(
    'relation' => 'AND',
  ),
);

// Фильтр для контракта
if (isset($_GET['contract']) && $_GET['contract'] !== '') {
    $args['meta_query'][] = array(
        'key' => 'contract',
        'value' => sanitize_text_field($_GET['contract']),
        'compare' => '='
    );
}

// Фильтр для количества комнат
if (isset($_GET['rooms']) && $_GET['rooms'] !== '') {
    $args['meta_query'][] = array(
        'key' => 'rooms',
        'value' => intval($_GET['rooms']),
        'compare' => '='
    );
}

// Если необходимо добавить другие фильтры, добавьте их аналогичным образом, как показано выше.

// Выполнение запроса
$query = new WP_Query($args);

if ($query->have_posts()) : 
    while ($query->have_posts()) : $query->the_post();
        // Ваш код для отображения постов
        the_title(); // Пример вывода заголовка
    endwhile;
else:
    echo 'Нет записей, соответствующих критериям фильтрации.';
endif;

wp_reset_postdata();

Пояснения к коду:

  • Мы создаём массив $args для запроса с нужными параметрами.
  • Исполняется фильтрация по полям contract и rooms, и только если значения были выбраны в форме.
  • Использование методов sanitize_text_field() и intval() помогает избежать потенциальных проблем с безопасностью, очищая входные данные.
  • После выполнения запроса, полученные записи выводятся в цикле while.
  • Важно вызывать wp_reset_postdata(), чтобы сбросить глобальные переменные $post после использования WP_Query.

Теперь этот код должен позволить вам успешно фильтровать ваши записи пользовательского типа по выбранным параметрам, а также сортировать их по цене в порядке возрастания или убывания.

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

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