Фильтрация по произвольному полю в произвольном типе записей на странице администратора

21 дек. 2015 г., 15:31:56
Просмотры: 37K
Голосов: 13

Я использовал Advanced Custom Fields для создания произвольных полей с названием соревнования, ответами и т.д. Я создал произвольный тип записи для соревнований, как показано на изображении, и использовал functions.php WordPress для создания колонок из значений моих произвольных полей.

Я пытаюсь добавить выпадающий список "Фильтровать по" с различными названиями/метками соревнований, как показано ниже, но я могу найти только решения с использованием таксономий, которые я предпочел бы не использовать если возможно, так как для всего остального я использовал только произвольные поля.

Возможно ли создать пользовательский выпадающий список "Фильтровать по" используя только произвольные поля?

Фильтр WordPress

2
Комментарии

Вы можете использовать хук restrict_manage_posts для добавления дополнительных выпадающих списков. Не забудьте также добавить логику для фильтра, так как WordPress не будет знать, что с ним делать "из коробки" (в отличие от выпадающих списков таксономий, которые он может обрабатывать автоматически).

David Gard David Gard
21 дек. 2015 г. 15:41:38

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

David Gard David Gard
21 дек. 2015 г. 17:10:11
Все ответы на вопрос 5
2
14

Для отображения результатов фильтрации используйте следующий код:

add_filter( 'parse_query', 'prefix_parse_filter' );
function prefix_parse_filter($query) {
   global $pagenow;
   $current_page = isset( $_GET['post_type'] ) ? $_GET['post_type'] : '';
   
   if ( is_admin() && 
     'competition' == $current_page &&
     'edit.php' == $pagenow && 
      isset( $_GET['competition-name'] ) && 
      $_GET['competition-name'] != '' ) {
   
    $competition_name                  = $_GET['competition-name'];
    $query->query_vars['meta_key']     = 'competition_name';
    $query->query_vars['meta_value']   = $competition_name;
    $query->query_vars['meta_compare'] = '=';
  }
}

Измените meta_key и meta_value по мере необходимости. В данном примере я использовал "competition_name" в качестве meta_key и "competition-name" в качестве имени выпадающего списка.

21 дек. 2015 г. 16:32:28
Комментарии

Отлично, мне было лень, поэтому я предложил ему задать дополнительный вопрос ;)

David Gard David Gard
21 дек. 2015 г. 17:11:00

Похоже, что 2 ответа составляют полный ответ и их следует объединить.

RCNeil RCNeil
10 июл. 2017 г. 20:28:07
2
11

Действие restrict_manage_posts запускает функцию add_extra_tablenav(), которая позволяет добавить дополнительные выпадающие списки в нужную таблицу списков.

В примере ниже мы сначала проверяем, что Тип записи корректен, затем получаем все значения из БД, сохраненные по ключу competition_name в таблице postmeta (вам нужно изменить имя ключа по необходимости). Запрос довольно простой: он проверяет, опубликован ли Конкурс, берет только уникальные значения (чтобы избежать дублирования в выпадающем списке) и сортирует их по алфавиту.

Далее мы проверяем наличие результатов (нет смысла выводить пустой выпадающий список), формируем опции (включая вариант по умолчанию для отображения всех) и выводим сам список.

Как упомянуто в комментарии, на этом история не заканчивается: вам понадобится логика, чтобы таблица списков отображала только нужные результаты при активном фильтре. Но это уже тема для отдельного вопроса, если потребуется помощь. Подсказка — посмотрите файлы /wp-admin/includes/class-wp-posts-list-table.php и его родителя .../wp-class-list-table.php.

/**
 * Добавляет дополнительные выпадающие списки в таблицы списков
 *
 * @param обязательный string $post_type    Отображаемый тип записи
 */
add_action('restrict_manage_posts', 'add_extra_tablenav');
function add_extra_tablenav($post_type){
    
    global $wpdb;
    
    /** Проверяем, что это нужный тип записи */
    if($post_type !== 'competition')
        return;
    
    /** Получаем результаты из БД */
    $query = $wpdb->prepare('
        SELECT DISTINCT pm.meta_value FROM %1$s pm
        LEFT JOIN %2$s p ON p.ID = pm.post_id
        WHERE pm.meta_key = "%3$s" 
        AND p.post_status = "%4$s" 
        AND p.post_type = "%5$s"
        ORDER BY "%6$s"',
        $wpdb->postmeta,
        $wpdb->posts,
        'competition_name', // Ваш мета-ключ — измените по необходимости
        'publish',          // Статус записи — измените по необходимости
        $post_type,
        'competition_name'
    );
    $results = $wpdb->get_col($query);
    
    /** Проверяем, есть ли что выводить */
    if(empty($results))
        return;

    // Получаем выбранную опцию, если она есть
    if (isset( $_GET['competition-name'] ) && $_GET['competition-name'] != '') {
        $selectedName = $_GET['competition-name'];
    } else {
        $selectedName = -1;
    }
    
    /** Формируем все опции для вывода */
    $options[] = sprintf('<option value="-1">%1$s</option>', __('Все конкурсы', 'your-text-domain'));
    foreach($results as $result) :
        if ($result == $selectedName) {
            $options[] = sprintf('<option value="%1$s" selected>%2$s</option>', esc_attr($result), $result);
        } else {
            $options[] = sprintf('<option value="%1$s">%2$s</option>', esc_attr($result), $result);
        }
    endforeach;

    /** Выводим выпадающий список */
    echo '<select class="" id="competition-name" name="competition-name">';
    echo join("\n", $options);
    echo '</select>';

}
21 дек. 2015 г. 16:18:17
Комментарии

При использовании этого кода я получаю ошибку Notice: wpdb::prepare was called incorrectly. The query does not contain the correct number of placeholders (6) for the number of arguments passed (5). Please see Debugging in WordPress for more information. (This message was added in version 4.8.3.) in /[...]/wp-includes/functions.php on line 4773

rassoh rassoh
10 июл. 2019 г. 14:28:10

Я также получаю такую же ошибку

Vasim Shaikh Vasim Shaikh
30 янв. 2020 г. 21:02:37
0

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

// Делаем пользовательские столбцы типа записи сортируемыми
function cpt_custom_columns_sortable( $columns ) {

    // Добавляем наши столбцы в массив $columns
    $columns['item_number'] = 'item_number';
    $columns['coat_school'] = 'coat_school'; 

    return $columns;
} add_filter( 'manage_edit-your-custom-post-type-slug_sortable_columns', 'cpt_custom_columns_sortable' );
9 апр. 2019 г. 18:46:04
0

Замените запрос ниже, чтобы исправить ошибку wpdb::prepare:

$query = $wpdb->prepare('
        SELECT DISTINCT pm.meta_value FROM %1$s pm
        LEFT JOIN %2$s p ON p.ID = pm.post_id
        WHERE pm.meta_key = "%3$s" 
        AND p.post_status = "%4$s" 
        AND p.post_type = "%5$s"
        ORDER BY "%3$s"',
        $wpdb->postmeta,
        $wpdb->posts,
        'competition_name', // Ваш мета-ключ - измените при необходимости
        'publish',          // Статус записи - измените при необходимости
        $post_type,
        'competition_name' // необходимо указать второй раз для определения "%3$s" в ORDER BY
  );
12 мар. 2020 г. 16:44:25
0

Я столкнулся с такой же проблемой, когда пытался фильтровать записи произвольного типа по произвольным полям.
Но я решил эту проблему, выполнив следующие шаги:
Изменил название произвольного поля с writer на _writer
Затем обновил следующий код внутри функции обратного вызова хука parse_query, чтобы добавить meta_query для произвольного поля:

$query->set( 'meta_query', array(
    array(
          'key'     => '_writer',
           'compare' => '=',
           'value'   => $_GET['_writer'],
           'type'    => 'numeric',
      )
) );         

Это решение сработало в моем случае.
Документация https://developer.wordpress.org/reference/hooks/pre_get_posts/
Полезные ссылки https://developer.wordpress.org/reference/hooks/pre_get_posts/#comment-2571
https://stackoverflow.com/questions/47869905/how-can-i-filter-records-in-custom-post-type-list-in-admin-based-on-user-id-that

8 июл. 2020 г. 01:19:25