web-dev-qa-db-ja.com

WordPressカスタム投稿タイプの管理領域をカスタムフィールドでソートする方法

私のカスタム投稿タイプの1つを編集するとき、私はそれらが公開された日付の代わりにカスタムフィールドによってすべてのエントリをリストできるようにしたいです(カスタム投稿タイプのためにおそらく関連性がない)。私はカスタム投稿タイプについてのブログ投稿のコメントからリードを得ました、そして、著者はそれが可能であって、あなたがカスタムソートのために列名をクリックできるようにそれを作ったとさえ言いました。彼は私が自分のコメントで書き留めた posts_orderby 関数について言及しましたが、今では私はもうブログ記事を見つけることができます。助言がありますか?私は使用した1つの解決策を見ました

add_action('wp', 'check_page');

check_page関数は add_filter を使ってクエリを変更しましたが、管理領域ではなくテーマファイルでのみ機能すると確信しています。

52
tooshel

あなたがおそらく答えが提供されていないことから想像できるように、解決策は正確には自明ではない。私がしたのは、カスタム投稿タイプ "movie"とカスタムフィールドキー "ジャンル"を想定した、やや自己完結型の例を作成することです。

免責事項:これはWP3.0で動作しますが、それが以前のバージョンで動作することを確信できません。

基本的には、2つのフックを機能させるために、もう2つのフックを明確かつ有用にするためにフックする必要があります。

最初のフックは 'restrict_manage_posts'で、投稿のリストの上の "Bulk Actions"と "Show Dates"がフィルタリングするHTMLの<select>を発行することができます。提供されたコードは、このスクリーンスニペットに見られるように "Sort by:"機能を生成します。

How to Create Sort By functionality for a Custom Post Type in the WordPress Admin
(出典: mikeschinkel.com

ポストタイプのすべてのmeta_keysのリストを提供するWordPress API関数がないため、コードは直接SQLを使用します(将来の trac ticket to me ...)のように聞こえます。とにかく、これがコードです。投稿タイプを$_GETから取得し、それが有効な投稿タイプpost_type_exists()であると同時にmovie投稿タイプであることを確認するために検証します(これら2つのチェックはやり過ぎですが、やりたくない場合はどのようにしますか。それはWordPressの他のものと衝突しないので最後に私はsortby URLパラメータを使います:

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

2番目に必要なステップは、WordPressがどのクエリを実行すべきかを決定した後、クエリを実行する前に呼び出されるparse_queryフックを使用することです。ここで、クエリのmeta_key配列に、 _ query_posts()orderbyパラメータのCodex に記載されています。)でorderbyquery_varの値を設定します。

  1. 私達は管理者です(is_admin())、
  2. 私たちは管理者($pagenow=='edit.php')の投稿を一覧表示するページにいます、
  3. ページがmovieと等しいpost_type URLパラメータで呼び出されました。
  4. このページは、sortbyというURLパラメータでも呼び出されており、 'None'の値が渡されていないこと

これらすべてのテストに合格したら、query_vars文書化された_(here )を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を追加してください。このフックはデフォルトの列の配列を渡されます。簡単にするために、2つの標準列に置き換えました。チェックボックス(cb)と投稿名(title)。 (posts_columnsprint_r()で検査して、他に何がデフォルトで利用可能かを調べることができます。)

sortbyというURLパラメータがあり、それがNoneではない場合には、 "Sorted By:"を追加することにしました。

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

最後に、適切な投稿タイプの投稿があり、is_admin()manage_pages_custom_columnの冗長なテストで、実際に値を表示するために$pagenow=='edit.php'フックを使用します。 sortbyというURLパラメータがあるとき、リストに表示されている並べ替えられているカスタムフィールドの値を抽出します。これは次のようなものです(これはテストデータですので、映画の分類に関するピーナッツギャラリーからのコメントはありません)。

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

これはmovieの最初の "ジャンル"、つまり与えられたキーに複数の値がある場合は最初のmeta_valueのみを取得することに注意してください。しかし、それでもそうでなければそれがどのように機能するかわからない!

そして、このコードをどこに置くかになじみがない人のために、あなたはそれをプラグインに入れるか、またはあなたの現在のテーマのfunctions.phpファイルに初心者のために置くことができます。

これはどのように役立ちますか。

66
MikeSchinkel

WordPress 3.1(私はベータ版を使用しています)の時点で、列はそれらのタイトルによってソート可能になりました。

次の投稿はそれらをどのように実装するかを詳しく述べています。

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

8
Leo Plaw