Стандартный список записей в админке WordPress позволяет фильтровать записи по категориям, датам и авторам, но часто требуется добавить фильтр по произвольным мета-полям (custom fields). В этой статье я подробно расскажу, как реализовать такой фильтр с примерами кода и практическими рекомендациями.
Почему стоит добавить фильтр по мета-полям
Мета-поля — это дополнительные данные, которые вы можете прикреплять к записям, страницам или любым кастомным типам записей. Например, у вас может быть магазин на WooCommerce, и вам нужно фильтровать товары по атрибутам, которые хранятся в мета-полях.
Стандартные фильтры WordPress не поддерживают мета-поля, поэтому без доработок админка не даст удобного способа отфильтровать записи по нужным параметрам.
Добавление такого фильтра улучшит удобство работы с большим количеством контента, ускорит поиск нужных записей и повысит продуктивность.
Добавляем выпадающий фильтр по мета-полю в админке WordPress
Рассмотрим пример, когда у нас есть кастомный тип записи product и мета-поле _wpsource_color — цвет товара. Задача — добавить в список товаров в админке фильтр по цвету.
Шаг 1: Добавляем выпадающий список фильтра в админке
Для этого используем хук restrict_manage_posts. Вот минимальный пример кода, который нужно добавить в файл functions.php вашей темы или в плагин:
function wpsource_add_color_filter() {
global $typenow;
if ($typenow !== 'product') return;
// Получаем уникальные значения мета-поля _wpsource_color
global $wpdb;
$colors = $wpdb->get_col($wpdb->prepare(
"SELECT DISTINCT meta_value FROM {$wpdb->postmeta} WHERE meta_key = %s ORDER BY meta_value ASC",
'_wpsource_color'
));
echo '<select name="wpsource_color_filter">';
echo '<option value="">Все цвета</option>';
foreach ($colors as $color) {
$selected = (isset($_GET['wpsource_color_filter']) && $_GET['wpsource_color_filter'] === $color) ? ' selected' : '';
echo '<option value="' . esc_attr($color) . '"' . $selected . '>' . esc_html($color) . '</option>';
}
echo '</select>';
}
add_action('restrict_manage_posts', 'wpsource_add_color_filter');Здесь мы выводим селект с уникальными значениями мета-поля _wpsource_color. Пользователь сможет выбрать нужный цвет для фильтрации.
Шаг 2: Применяем фильтрацию запросов по выбранному значению
Чтобы фильтр заработал, нужно изменить основной запрос WordPress, добавив условие по мета-полю. Это делается через хук pre_get_posts:
function wpsource_apply_color_filter($query) {
global $pagenow;
$post_type = isset($_GET['post_type']) ? $_GET['post_type'] : '';
if ($pagenow === 'edit.php' && $post_type === 'product' && !empty($_GET['wpsource_color_filter'])) {
$meta_query = array(
array(
'key' => '_wpsource_color',
'value' => sanitize_text_field($_GET['wpsource_color_filter']),
'compare' => '='
)
);
$query->set('meta_query', $meta_query);
}
}
add_action('pre_get_posts', 'wpsource_apply_color_filter');Этот код добавляет к основному запросу условие, которое ограничивает выборку только записями с нужным цветом.
Оптимизация и кэширование для фильтров по мета-полям
Запрос к базе для получения уникальных значений мета-поля может быть дорогим на больших сайтах. Чтобы избежать замедления, стоит кешировать результаты.
Пример кеширования с помощью Transients API:
function wpsource_get_colors_cached() {
$cache_key = 'wpsource_colors_list';
$colors = get_transient($cache_key);
if ($colors === false) {
global $wpdb;
$colors = $wpdb->get_col($wpdb->prepare(
"SELECT DISTINCT meta_value FROM {$wpdb->postmeta} WHERE meta_key = %s ORDER BY meta_value ASC",
'_wpsource_color'
));
set_transient($cache_key, $colors, DAY_IN_SECONDS);
}
return $colors;
}
function wpsource_add_color_filter_optimized() {
global $typenow;
if ($typenow !== 'product') return;
$colors = wpsource_get_colors_cached();
echo '<select name="wpsource_color_filter">';
echo '<option value="">Все цвета</option>';
foreach ($colors as $color) {
$selected = (isset($_GET['wpsource_color_filter']) && $_GET['wpsource_color_filter'] === $color) ? ' selected' : '';
echo '<option value="' . esc_attr($color) . '"' . $selected . '>' . esc_html($color) . '</option>';
}
echo '</select>';
}
remove_action('restrict_manage_posts', 'wpsource_add_color_filter');
add_action('restrict_manage_posts', 'wpsource_add_color_filter_optimized');Таким образом уникальные значения мета-поля будут запрашиваться из БД не чаще раза в сутки, что значительно снижает нагрузку.
Примеры полезных плагинов для расширения фильтров в админке
Если не хочется писать код, можно воспользоваться готовыми решениями:
- Admin Columns — позволяет добавлять в таблицы админки колонки и фильтры по произвольным полям.
- Clearfy Pro — оптимизационный плагин с расширенными возможностями для работы с админкой и фильтрами.
Однако для тонкой настройки и специфичных требований лучше писать собственные решения, как в примерах выше.
Расширение фильтрации: несколько мета-полей и типы данных
Если нужно фильтровать сразу по нескольким мета-полям, то в pre_get_posts нужно добавить несколько условий в массив meta_query с правильными операторами relation ('AND' или 'OR').
Пример:
function wpsource_apply_multi_meta_filter($query) {
global $pagenow;
$post_type = isset($_GET['post_type']) ? $_GET['post_type'] : '';
if ($pagenow === 'edit.php' && $post_type === 'product') {
$meta_query = array('relation' => 'AND');
if (!empty($_GET['wpsource_color_filter'])) {
$meta_query[] = array(
'key' => '_wpsource_color',
'value' => sanitize_text_field($_GET['wpsource_color_filter']),
'compare' => '='
);
}
if (!empty($_GET['wpsource_size_filter'])) {
$meta_query[] = array(
'key' => '_wpsource_size',
'value' => sanitize_text_field($_GET['wpsource_size_filter']),
'compare' => '='
);
}
if (count($meta_query) > 1) {
$query->set('meta_query', $meta_query);
}
}
}
add_action('pre_get_posts', 'wpsource_apply_multi_meta_filter');Также стоит помнить, что при числовых значениях мета-полей удобнее использовать параметр 'type' => 'NUMERIC' и операторы сравнения (<, >, BETWEEN) для диапазонов.
Вывод
Добавление фильтрации по мета-полям в админке WordPress — мощный инструмент для работы с контентом, который можно реализовать своими силами с помощью хуков и простого SQL-запроса. Оптимизация и кеширование помогут избежать проблем с производительностью. При необходимости можно использовать готовые плагины, но для специфичных задач лучше писать собственные решения.