wppartner.ru wordpress WP Partner

Создание комплексного фильтра постов WordPress с помощью мета-запросов

В этой статье мы рассмотрим, как создать сложный фильтр постов в WordPress, используя WP_Query с мета-запросами (meta_query). Такой функционал актуален для сайтов с большим количеством контента, где нужно реализовать фильтрацию по нескольким пользовательским полям одновременно, например, для каталога товаров, недвижимости или портфолио.

Почему стандартный фильтр WordPress не всегда подходит

Стандартный фильтр WordPress по категориям или таксономиям часто ограничен, если вы хотите фильтровать записи по нескольким параметрам, которые хранятся в пользовательских полях. Например, нужно отфильтровать объявления по цене, городу, состоянию и дате публикации. Для этого придется использовать мета-запросы.

Но простое использование meta_query быстро становится громоздким, если запросов много и нужно комбинировать условия AND и OR.

Кроме того, чтобы пользователь мог выбирать параметры фильтра на фронтенде, нужно реализовать удобный интерфейс и обработку формы.

Основы meta_query: синтаксис и примеры

Массив meta_query позволяет указать несколько условий к пользовательским полям. Каждое условие — массив с ключами:

  • key — имя мета-поля;
  • value — значение для сравнения;
  • compare — оператор сравнения (например, '=', '!=', 'LIKE', 'BETWEEN');
  • type — тип данных (например, 'NUMERIC', 'CHAR');

Пример запроса с двумя условиями AND:

$args = [
  'post_type' => 'post',
  'meta_query' => [
    'relation' => 'AND',
    [
      'key' => 'price',
      'value' => 1000,
      'compare' => '>=',
      'type' => 'NUMERIC',
    ],
    [
      'key' => 'city',
      'value' => 'Moscow',
      'compare' => '=',
    ],
  ],
];
$query = new WP_Query($args);

Этот запрос вернет посты с ценой от 1000 и городом Москва.

Как создать комплексный фильтр с несколькими параметрами и отношениями

В сложных случаях нужно комбинировать условия с разными отношениями. Например, фильтровать по цене (BETWEEN 1000 и 5000) и по городу (Москва или Санкт-Петербург). Для этого relation может быть 'AND' или 'OR', и внутри массива условий могут быть вложенные массивы с собственными relation.

Пример:

$args = [
  'post_type' => 'listing',
  'meta_query' => [
    'relation' => 'AND',
    [
      'key' => 'price',
      'value' => [1000, 5000],
      'compare' => 'BETWEEN',
      'type' => 'NUMERIC',
    ],
    [
      'relation' => 'OR',
      [
        'key' => 'city',
        'value' => 'Moscow',
        'compare' => '=',
      ],
      [
        'key' => 'city',
        'value' => 'Saint Petersburg',
        'compare' => '=',
      ],
    ],
  ],
];
$query = new WP_Query($args);

Такой запрос вернет все объекты с ценой от 1000 до 5000 и расположенные либо в Москве, либо в Санкт-Петербурге.

Практическая реализация: фильтр на фронтенде с формой

Для удобства пользователей нужно сделать HTML-форму, где можно выбрать параметры фильтрации:

  • Поле ввода минимальной и максимальной цены;
  • Выпадающий список или чекбоксы городов;
  • Дополнительные опции (например, состояние объекта).

Пример формы:

<form method="GET" action="">
  <label>Мин. цена:</label>
  <input type="number" name="price_min" />
  <label>Макс. цена:</label>
  <input type="number" name="price_max" />
  <label>Город:</label>
  <select name="city">
    <option value="">Все</option>
    <option value="Moscow">Москва</option>
    <option value="Saint Petersburg">Санкт-Петербург</option>
  </select>
  <input type="submit" value="Фильтровать" />
</form>

Обработка параметров в шаблоне:

function wppartner_filter_query_args($query_args) {
  if (!empty($_GET['price_min']) || !empty($_GET['price_max']) || !empty($_GET['city'])) {
    $meta_query = ['relation' => 'AND'];

    if (!empty($_GET['price_min']) && !empty($_GET['price_max'])) {
      $meta_query[] = [
        'key' => 'price',
        'value' => [(int)$_GET['price_min'], (int)$_GET['price_max']],
        'compare' => 'BETWEEN',
        'type' => 'NUMERIC',
      ];
    } elseif (!empty($_GET['price_min'])) {
      $meta_query[] = [
        'key' => 'price',
        'value' => (int)$_GET['price_min'],
        'compare' => '>=',
        'type' => 'NUMERIC',
      ];
    } elseif (!empty($_GET['price_max'])) {
      $meta_query[] = [
        'key' => 'price',
        'value' => (int)$_GET['price_max'],
        'compare' => '<=',
        'type' => 'NUMERIC',
      ];
    }

    if (!empty($_GET['city'])) {
      $meta_query[] = [
        'key' => 'city',
        'value' => sanitize_text_field($_GET['city']),
        'compare' => '=',
      ];
    }

    $query_args['meta_query'] = $meta_query;
  }
  return $query_args;
}

add_action('pre_get_posts', function($query) {
  if ($query->is_main_query() && !is_admin() && is_post_type_archive('listing')) {
    $args = $query->query_vars;
    $args = wppartner_filter_query_args($args);
    foreach ($args as $key => $value) {
      $query->set($key, $value);
    }
  }
});

Используем плагины для расширения возможностей фильтрации

Если хочется не писать весь код самостоятельно, можно использовать плагины с поддержкой meta_query и кастомных фильтров:

  • Clearfy Pro — оптимизация и расширение фильтров, в том числе по метаполям;
  • ABC Pagination — для удобной навигации по результатам фильтрации;
  • WPRemark — для сбора отзывов и оценки результатов фильтра;

Эти инструменты позволят быстро собрать мощный фильтр без глубокого погружения в код.

Советы по оптимизации запросов с meta_query

Мета-запросы могут сильно нагрузить базу данных, особенно если таблица wp_postmeta не оптимизирована. Рекомендации:

  • Добавьте индексы на поля meta_key и meta_value в базе данных;
  • Используйте числовые типы данных для числовых полей и указывайте type => 'NUMERIC' в запросах;
  • Минимизируйте количество условий в meta_query;
  • Кешируйте результаты фильтра с помощью Transients API или плагинов кэширования;
  • Если фильтрация становится очень сложной, рассмотрите перенос части данных в кастомные таблицы.

Пример добавления индекса MySQL для мета-поля price

ALTER TABLE wp_postmeta ADD INDEX meta_key_price (meta_key(191));

Индексация ускоряет поиск по ключу, что существенно снижает время ответа на фильтрацию.

Заключение: гибкость и масштабируемость

Создание многоуровневого фильтра постов через meta_query в WordPress — мощный инструмент для кастомизации вывода. Благодаря правильной структуре запросов, обработке параметров с фронтенда и оптимизации базы данных можно реализовать удобный и быстрый поиск по любым параметрам.

Использование плагинов из экосистемы WPShop, например, Clearfy Pro для оптимизации и ABC Pagination для навигации, поможет быстро развернуть готовое решение.

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

×
Делай сайт лучше!!

-20% на премиум темы и плагины

Использовать скидку ⋙