問題描述

當編輯我的一個自定義帖子型別時,我希望能夠透過自定義欄位而不是釋出日期列出所有條目 (對於自定義帖子型別可能不相關) 。我從一篇關於自定義帖子型別的部落格文章的評論中得到了一個引導,作者表示這是可能的,他甚至可以點選列名稱進行自定義排序。他提到了 posts_orderby 功能,我在自己的評論中注意到,但現在我可以找到部落格了。有什麼建議麼?我看到一個使用的解決方案

add_action('wp', 'check_page');

check_page 功能使用 add_filter 更改查詢,但我很確定它只能在主題檔案中工作,而不在管理區域。

最佳解決方案

正如你可能想象的缺乏提供的答案,解決方案並不是微不足道的。我所做的是建立一個有點 self-contained 示例,它假定自定義帖子型別的 「movie」 和”Genre” 的自定義欄位鍵。

免責宣告:這適用於 WP3.0,但我無法確定它將與早期版本一起使用。

你基本上需要鉤兩 (2) 個鉤來使它工作,另外兩個 (2) 使它變得明顯有用。

第一個鉤子是’restrict_manage_posts‘,它允許您在 「批次操作」 和 「顯示日期」 過濾器的帖子列表上方釋出一個 HTML <select> 。提供的程式碼將生成 「Sort by:」 功能,如此螢幕程式碼片段所示:

程式碼使用直接 SQL,因為沒有一個 WordPress API 函式來提供一個 post 型別的所有 meta_key 的列表 (聽起來像是一個未來的 trac 票給我…) 無論如何,這裡是程式碼。請注意,它從 $_GET 抓取帖子型別,並確認它是一個有效的帖子型別 post_type_exists()以及作為一個 movie 的帖子型別 (這兩個檢查是過度的,但我做到了,如果你不想要到 hard-code 的帖子型別。) 最後我使用 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);
        }
    }
}

第二個必需步驟是使用在 WordPress 決定一個應該執行的查詢之後但在執行查詢之前呼叫的 parse_query 鉤子。在這裡,我們可以在 query_posts()引數的 orderby 引數中的 query_var 陣列中設定 orderbymeta_key 的值。我們測試以確保:

  1. 我們在管理員 (is_admin()),
  2. 我們在頁面上列出管理員 ($pagenow=='edit.php') 中的帖子,
  3. 已使用等於 moviepost_type URL 引數呼叫該頁面,以及
  4. 該頁面也使用 sortby URL 引數呼叫,並且未透過’None’ 的值

如果所有這些測試透過,我們將 query_vars(如所述 here) 設定為 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) 。 (您可以使用 print_r()檢查 posts_columns,以檢視預設情況下可用的) 。

當我有一個 sortby URL 引數時,我決定新增一個 「Sorted By:」,當它不是 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 引數時,我們提取透過在列表中顯示它排序的自定義欄位值。這是它的樣子 (記住,這是測試資料,所以沒有評論從花生畫廊上的電影分類:) :):

這裡是程式碼:

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;
        }
    }
}

請注意,這隻會為 movie 提供第一個”Genre”,即給定鍵多個值的第一個 meta_value 。但是再一次,我不知道如何工作,否則!

而對於那些不熟悉這個程式碼的人來說,你可以把它放在一個外掛中,或者更有可能在你當前主題的 functions.php 檔案中使用新手。

這有助於

次佳解決方案

從 WordPress 3.1(我正在使用 beta) 列現在可以透過他們的標題排序。

以下帖子詳細介紹瞭如何實現它們。

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

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。