it-swarm.xyz

WordPress по настраиваемому полю

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

add_action('wp', 'check_page');

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

52
tooshel

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

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

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

Первый хук - это restrict_manage_posts, который позволяет вам генерировать HTML <select> в области над списком сообщений, где фильтруются "Bulk Actions" и "Show Dates". Предоставленный код будет генерировать функциональность "Sort by:", как показано в следующем фрагменте экрана:

 How to Create Sort By functionality for a Custom Post Type in the WordPress Admin 
(источник: mikeschinkel.com )

В коде используется прямой SQL, потому что нет функции API WordPress для предоставления списка всех meta_keys для типов сообщений (звучит как будущий trac ticket to me ...) В любом случае, вот код. Обратите внимание, что он извлекает тип записи из $_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\">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. Страница была вызвана с параметром 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(), чтобы узнать, что еще доступно по умолчанию.)

Я решил добавить "Sorted By:", когда есть параметр 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' => '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'. При наличии параметра URL sortby мы извлекаем значение настраиваемого поля, которое сортируется, отображая его в нашем списке. Вот как это выглядит (помните, это тестовые данные, поэтому нет комментариев из галереи арахиса о классификации фильмов! :):

 Custom Columns added for a Custom Post Type in the 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;
        }
    }
}

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

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

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

66
MikeSchinkel

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

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

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

8
Leo Plaw