WebDesign Dackel

WordPressで著者別のカテゴリー一覧を取得、表示する

WordPressで著者別のカテゴリー一覧を取得、表示する

Hatena0
Google+0
Pocket0
Feedly0

少し珍しいパターンかとは思いますが、WordPressで著者に関連したカテゴリーを取得したい、という場面がありました。

実現したい内容

言葉では少しイメージが付きづらいですが、やりたい事は下記のようなことです。
著者一覧と、その著者が書いているカテゴリーが一覧で出てくる。というイメージです。
サイト内で複数の編集者いて、それぞれ別々のカテゴリ記事を書いている時なんかに使えるんじゃ無いかと思います。

wp_author_categories_img01

なんだかおかしなサイト構成ですが、筆者が担当するカテゴリが違う、ということが言いたいわけです!

自前の関数を実装

調べて見た感じだと、該当する関数が用意されていないみたいだったので自前で実装してみました。
(用意されていないくらいなので需要がそもそも無いかと思いますが…)

/**
 * get_author_terms
 * 指定した著者に関連するターム(カテゴリー,タグ)一覧を取得します
 * @param integer $author_id
 * @param array $args
 * @param boolean $link
 */
function get_author_terms( $author_id=null, $args=array() )
{
    global $wpdb;

    // 著者IDの指定が無ければ、現在の著者情報を使用する
    if( empty($author_id) ){
        $author_id = get_the_author_meta("ID");
    }else{
        $author_id = intval($author_id);
    }

    // デフォルトのパラメータとマージ
    $args = array_merge(array(
        "taxonomy"    => "category", //タクソノミー
        "post_status" => "publish",  //投稿のステータス
        "order"       => "ASC",      //並び順 'ASC' or 'DESC'
        "orderby"     => "name"      //termのカラム名を指定します
    ), $args);

    // パラメータを調整
    $args["orderby"] = "terms.".$args["orderby"];

    // SQL文を生成し実行
    $results = $wpdb->get_results($wpdb->prepare("
        SELECT DISTINCT terms.term_Id
        FROM {$wpdb->terms} AS terms
        INNER JOIN {$wpdb->term_taxonomy} AS tax
            ON tax.term_id = terms.term_id
        INNER JOIN {$wpdb->term_relationships} AS rel
            ON rel.term_taxonomy_id = tax.term_taxonomy_id
        INNER JOIN {$wpdb->posts} AS posts
            ON posts.ID = rel.object_id
        WHERE tax.taxonomy = %s
        AND post_author = %d
        AND post_status = %s
        ORDER BY %s %s
    ",
    $args["taxonomy"], $author_id, $args["post_status"], $args["orderby"], $args["order"]));

    // 取得したIDから、タームオブジェクトを生成
    $terms = array();
    foreach( $results as $obj ){
        $terms[] = get_term($obj->term_Id, $args["taxonomy"]);
    }

    return $terms;
}

何をやっているかというと、terms, term_relationships, posts, taxonomyテーブルをそれぞれINNER JOINして、posts.post_authorに著者IDを指定しています。
ただ、これだけだとカテゴリIDが重複したものまで返ってくるので、DISTINCTで重複した行を除外してterm.term_Idを取得します。

そのIDを元にカテゴリを取得する、という流れになっています。(もっと良い方法があれば是非ご教授頂きたいですっ!)

一応、デフォルトではカテゴリーを取得する様になっていますが、引数に渡すオプションでタグなども取得することが出来ます。

関数の使い方

そして、このget_author_terms()関数で、指定した著者に関連したカテゴリーを取得するにはこんな感じで使用します。

<dl>
    <?php
    $users = get_users();
    foreach( $users as $user ) : $categories = get_author_terms( $user->ID ); ?>
    <dt><?php the_author_meta("display_name", $user->ID); ?> さん</dt>
    <dd>
        <ul>
            <?php foreach( $categories as $category ) : ?>
            <li><a href="<?php print get_category_link($category->term_id); ?>"><?php print $category->name; ?></a></li>
            <?php endforeach; ?>
        </ul>
    </dd>
    <?php endforeach; ?>
</dl>

上記サンプルでは、ユーザー一覧を取得して、関連するカテゴリーをリスト表示、というようなことをやっています。
カテゴリでは無く、タグを取得する場合はtaxonomy"post_tag"を渡します。

$tags = get_author_terms($user->ID,array(
    "taxonomy" => "post_tag"
));

これで、著者に関連したタグ一覧が取得出来ました。

取得する値を変えたい、この値も取得したい、なんて時はphpMyAdminやCodex、ターミナルなんかからWPのテーブル構造を確認してみてください。

データベース構造 – WordPress Codex 日本語版

冒頭にも書いたようにあまり需要がなさそうなところですが、誰かのお役に立てれば幸いです。