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

52

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

add_action('wp', 'check_page');

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

tooshel
источник
1
Вот еще один полезный ответ, чтобы отсортировать сообщения по ... <br/> wordpress.stackexchange.com/questions/66455/…
T.Todua

Ответы:

66

Как вы можете, вероятно, догадаться по отсутствию ответов, решение не совсем тривиально. Что я сделал, так это создал несколько автономный пример, который предполагает собственный тип записи " movie" и ключ настраиваемого поля " Жанр ".

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

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

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

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

Код использует прямой SQL , потому что это не функция WordPress API , чтобы обеспечить список всех meta_keys на пост типов (звучит как будущий Trac билет мне ...) Во всяком случае, вот код. Обратите внимание, что он извлекает тип записи из $_GETи проверяет, чтобы убедиться, что это и правильный тип записи, post_type_exists()и movieтип записи (эти две проверки являются избыточными, но я сделал это, чтобы показать вам, как, если вы не хотите закодируйте тип сообщения.) Наконец, я использую sortbyпараметр URL, поскольку он не конфликтует ни с чем в 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\">No Sort</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 "Sort by: " . implode("\n",$html);
        }
    }
}

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

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

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

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()чтобы увидеть, что еще доступно по умолчанию.)

Я решил добавить « Sorted By: », когда есть sortbyпараметр URL, а когда его нет 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' => 'Movie Name',
        );
    if (isset($_GET['sortby']) && $_GET['sortby'] !='None') 
        $posts_columns['meta_value'] = 'Sorted By';

    return $posts_columns;
}

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

Пользовательские столбцы добавлены для пользовательского типа публикации в WordPress Admin
(источник: 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;
        }
    }
}

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

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

Как это помогает

MikeSchinkel
источник
2
+1, только за усилие. Но было бы еще лучше, если бы круги были нарисованы от руки :-)
Ян Фабри
Любая идея, как полностью удалить фильтр ПОКАЗАТЬ ВСЕ ДАТЫ, чтобы только для моих типов записей отображались только мои пользовательские фильтры?
RailsTweeter
@RailsTweeter Используйте технику, которую я показал здесь, где два крючка, которые заключают в себе HTML-генерацию, 'months_dropdown_results'и 'restrict_manage_posts'. PS Upvotes всегда приветствуются. :)
MikeSchinkel
@MikeSchinkel, теперь, когда есть WP API, это немного обновит ваш код?
samjco
@samjco Не уверен. У меня, к сожалению, нет времени, чтобы пересмотреть это в данный момент.
MikeSchinkel
-1

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

/* --------Sortable Events on Dashboard - show start date, time, venue--------- */

/*-------------------------------------------------------------------------------
    Custom Columns
-------------------------------------------------------------------------------*/

function my_*YOUR POST TYPE*_columns($columns)
{
    $columns = array(
        'cb'        => '<input type="checkbox" />',
        'title'     => 'Title',
        'your_custom_field'     => 'Custom Field Name',          
        'date'      =>  '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");

/*-------------------------------------------------------------------------------
    Sortable 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_custom_field'

Джейк
источник