Как отсортировать записи произвольного типа в админке WordPress по произвольному полю

11 авг. 2010 г., 23:16:49
Просмотры: 37.3K
Голосов: 55

При редактировании одного из моих произвольных типов записей я хочу иметь возможность отображать все записи, отсортированные по произвольному полю, вместо даты их публикации (которая для произвольного типа записей, вероятно, не имеет значения). Я нашел подсказку в комментариях к статье о произвольных типах записей, где автор сказал, что это возможно, и что он даже сделал так, чтобы можно было кликать по названиям столбцов для выполнения пользовательской сортировки. Он упомянул функцию posts_orderby, что я отметил в своих комментариях, но теперь я не могу найти эту статью. Есть предложения? Я видел одно решение, которое использовало

add_action('wp', 'check_page');

И функция check_page использовала add_filter для изменения запроса, но я почти уверен, что это будет работать только в файлах темы, а не в админ-панели.

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

Еще один полезный ответ о сортировке записей по ....<br/> http://wordpress.stackexchange.com/questions/66455/how-to-change-order-of-posts-in-admin

T.Todua T.Todua
22 мая 2014 г. 22:33:20
Все ответы на вопрос 3
5
68

Как вы, наверное, догадались по отсутствию предоставленных ответов, решение не совсем тривиальное. Я создал относительно самодостаточный пример, который предполагает наличие пользовательского типа записи "movie" и пользовательского поля с ключом "Genre".

Отказ от ответственности: это работает с WP3.0, но я не могу быть уверен, что будет работать с более ранними версиями.

Вам в основном нужно подключить два (2) хука, чтобы это работало, и ещё два (2), чтобы сделать это очевидным и полезным.

Первый хук — 'restrict_manage_posts', который позволяет вам вывести HTML <select> в области над списком записей, где находятся фильтры "Массовые действия" и "Показать по датам". Предоставленный код создаст функционал "Сортировать по:", как показано на этом скриншоте:

Как создать функционал 'Сортировать по' для пользовательского типа записи в админке WordPress
(источник: mikeschinkel.com)

Код использует прямой SQL, потому что в WordPress нет API-функции для получения списка всех meta_key для типов записей (звучит как будущий тикет для trac...). В любом случае, вот код. Обратите внимание, что он получает тип записи из $_GET и проверяет, является ли он допустимым типом записи post_type_exists(), а также типом записи movie (эти две проверки избыточны, но я добавил их, чтобы показать, как можно избежать жёсткого кодирования типа записи). Наконец, я использую параметр URL sortby, так как он не конфликтует ни с чем другим в WordPress:

add_action('restrict_manage_posts','restrict_manage_movie_sort_by_genre');
function restrict_manage_movie_sort_by_genre() {
    if (isset($_GET['post_type'])) {
        $post_type = $_GET['post_type'];
        if (post_type_exists($post_type) && $post_type=='movie') {
            global $wpdb;
            $sql=<<<SQL
SELECT pm.meta_key FROM {$wpdb->postmeta} pm
INNER JOIN {$wpdb->posts} p ON p.ID=pm.post_id
WHERE p.post_type='movie' AND pm.meta_key='Genre'
GROUP BY pm.meta_key
ORDER BY pm.meta_key
SQL;
            $results = $wpdb->get_results($sql);
            $html = array();
            $html[] = "<select id=\"sortby\" name=\"sortby\">";
            $html[] = "<option value=\"None\">Без сортировки</option>";
            $this_sort = $_GET['sortby'];
            foreach($results as $meta_key) {
                $default = ($this_sort==$meta_key->meta_key ? ' selected="selected"' : '');
                $value = esc_attr($meta_key->meta_key);
                $html[] = "<option value=\"{$meta_key->meta_key}\"$default>{$value}</option>";
            }
            $html[] = "</select>";
            echo "Сортировать по: " . implode("\n",$html);
        }
    }
}

Второй необходимый шаг — использовать хук parse_query, который вызывается после того, как WordPress определит, какой запрос должен выполнить, но перед его выполнением. Здесь мы можем установить значения orderby и meta_key в массиве query_var запроса, которые документированы в Codex в параметре orderby для query_posts(). Мы проверяем, что:

  1. Мы находимся в админке (is_admin()),
  2. Мы на странице, которая отображает записи в админке ($pagenow=='edit.php'),
  3. Страница была вызвана с параметром URL post_type, равным movie, и
  4. Страница также была вызвана с параметром URL sortby, и его значение не 'None'

Если все эти проверки пройдены, мы устанавливаем query_vars (как документировано здесь) в meta_value и наше значение sortby для 'Genre':

add_filter( 'parse_query', 'sort_movie_by_meta_value' );
function sort_movie_by_meta_value($query) {
    global $pagenow;
    if (is_admin() && $pagenow=='edit.php' &&
        isset($_GET['post_type']) && $_GET['post_type']=='movie' && 
        isset($_GET['sortby'])  && $_GET['sortby'] !='None')  {
        $query->query_vars['orderby'] = 'meta_value';
        $query->query_vars['meta_key'] = $_GET['sortby'];
    }
}

И это всё, что вам нужно сделать; никаких хуков "posts_order" или "wp" не требуется! Конечно, вам нужно сделать больше; вам нужно добавить некоторые столбцы на странице, которая отображает записи, чтобы вы могли видеть значения, по которым происходит сортировка, иначе пользователи будут в замешательстве. Поэтому добавляем хук manage_{$post_type}_posts_columns, в данном случае manage_movie_posts_columns. Этот хук получает массив столбцов по умолчанию, и для простоты я просто заменил его двумя стандартными столбцами: чекбоксом (cb) и названием записи (title). (Вы можете исследовать posts_columns с помощью print_r(), чтобы увидеть, что ещё доступно по умолчанию.)

Я решил добавить "Сортировка по:", когда есть параметр URL sortby и он не равен None:

add_action('manage_movie_posts_columns', 'manage_movie_posts_columns');
function manage_movie_posts_columns($posts_columns) {
    $posts_columns = array(
        'cb' => $posts_columns['cb'],
        'title' => 'Название фильма',
        );
    if (isset($_GET['sortby']) && $_GET['sortby'] !='None') 
        $posts_columns['meta_value'] = 'Сортировка по';

    return $posts_columns;
}

Наконец, мы используем хук manage_pages_custom_column для отображения значения, когда есть запись соответствующего типа и с, возможно, избыточной проверкой на is_admin() и $pagenow=='edit.php'. Когда есть параметр URL sortby, мы извлекаем значение пользовательского поля, по которому происходит сортировка, и отображаем его в нашем списке. Вот как это выглядит (помните, это тестовые данные, так что никаких комментариев насчёт классификации фильмов! :):

Добавление пользовательских столбцов для пользовательского типа записи в админке WordPress
(источник: mikeschinkel.com)

И вот код:

add_action('manage_pages_custom_column', 'manage_movie_pages_custom_column',10,2);
function manage_movie_pages_custom_column($column_name,$post_id) {
    global $pagenow;
    $post = get_post($post_id);
    if ($post->post_type=='movie' && is_admin() && $pagenow=='edit.php')  {
        switch ($column_name) {
            case 'meta_value':
                if (isset($_GET['sortby']) && $_GET['sortby'] !='None') {
                    echo get_post_meta($post_id,$_GET['sortby'],true);
                }
                break;
        }
    }
}

Обратите внимание, что это учитывает только первый "Genre" для movie, т.е. первое значение meta_value в случае нескольких значений для данного ключа. Но, опять же, я не уверен, как это могло бы работать иначе!

Для тех, кто не знает, куда вставить этот код, вы можете добавить его в плагин или, что более вероятно для новичков, в файл functions.php вашей текущей темы.

Надеюсь, это поможет.

12 авг. 2010 г. 04:13:49
Комментарии

+1, только за усилия. Но было бы еще лучше если бы круги были нарисованы от руки :-)

Jan Fabry Jan Fabry
12 авг. 2010 г. 10:34:03

Есть идеи как полностью убрать фильтр ПОКАЗАТЬ ВСЕ ДАТЫ, чтобы отображались только мои пользовательские фильтры для определенного типа записей?

RailsTweeter RailsTweeter
22 мая 2014 г. 20:02:41

@RailsTweeter Используй технику, которую я показал здесь, где два хука, обрамляющие генерацию HTML, это 'months_dropdown_results' и 'restrict_manage_posts'. P.S. Апвоуты всегда приветствуются. :)

MikeSchinkel MikeSchinkel
23 мая 2014 г. 02:56:47

@MikeSchinkel , теперь, когда есть WP API, это как-то обновит ваш код?

samjco-com samjco-com
16 февр. 2019 г. 22:23:09

@samjco Не уверен. К сожалению, у меня сейчас нет времени, чтобы пересмотреть это.

MikeSchinkel MikeSchinkel
17 февр. 2019 г. 04:53:09
0

Начиная с WordPress 3.1 (я использую бета-версию), столбцы теперь можно сортировать по их заголовкам.

В следующей статье подробно описано, как их реализовать.

http://scribu.net/wordpress/custom-sortable-columns.html

12 дек. 2010 г. 14:23:06
0
-1

Вот простое решение:

/* --------Сортируемые события в админке - показывать дату начала, время, место--------- */

/*-------------------------------------------------------------------------------
    Пользовательские колонки
-------------------------------------------------------------------------------*/

function my_*YOUR POST TYPE*_columns($columns)
{
    $columns = array(
        'cb'        => '<input type="checkbox" />',
        'title'     => 'Заголовок',
        'your_custom_field'     => 'Имя пользовательского поля',          
        'date'      =>  'Дата',
    );
    return $columns;
}

function my_custom_columns($column)
{
    global $post;
    if($column == 'your_custom_field')
    {
        if(get_post_meta($post->ID, 'your_custom_field', true);)
        {
            echo get_post_meta($post->ID, 'your_custom_field', true);
        }
    }

}

add_action("manage_posts_custom_column", "my_custom_columns");
add_filter("manage_edit-*YOUR POST TYPE*_columns", "my_events_columns");

/*-------------------------------------------------------------------------------
    Сортируемые колонки
-------------------------------------------------------------------------------*/

function my_column_register_sortable( $columns )
{
    $columns['your_custom_field'] = 'your_custom_field';
    return $columns;
}

add_filter("manage_edit-*YOUR POST TYPE*_sortable_columns", "my_column_register_sortable" );

Просто замените YOUR POST TYPE и 'your_custom_field'

16 мая 2016 г. 15:57:05