WordPressで最上層のカテゴリーを取得するTips

topcategory

WordPressで、上の画像のようなトップイメージのあるブログを構築して、
カテゴリーが

  • Photo » Night
  • Photo » Dog
  • Photo » Night » Star

のいずれの場合でも「Photo」のイメージを出したい…という場合
「現在のカテゴリーを含む、いちばん上の階層のカテゴリー」の情報を取得する必要があります。

これにはいろいろな方法がありますが、
「表示名を取得する方法」と「IDを取得する方法」の二種類を紹介します。

2009.04.11追記
親子判定だけが目的であれば、もっと簡単な方法がありました。
»MovableType・WordPressでカテゴリーの親子関係を判定する

1. 各エントリーのIDを取得する

どちらの方法を使うにしても、まず
「現在のエントリーが属しているカテゴリーのID」を調べることになります。

カテゴリーアーカイブの場合は、変数「$cat」に既に値が入っていますが、個別アーカイブなどでは以下のようにPHPスクリプトを書きます。

説明

記事のID($post->ID)を引数として、get_the_category()でカテゴリー情報を取得します。
カテゴリーが複数指定されている可能性があるので、関数の返り値は配列になっています。そこで、$catArr[0]として、最初のカテゴリーだけを取ります(ひとつしか指定していない場合でも、0番目には絶対入っているはずです)。
MovableTypeと違い、残念ながら主カテゴリーを明示・取得することはできません。


$catにカテゴリーIDを入れた後は、以下のどちらかの方法を使います。

2-a. 表示名を取得する方法

以下の関数をテーマファイル内に追加します。

こういったユーザー関数は記事表示部分ではなく、テーマファイル内の「functions.php」に追加してください。あとで何度でも呼び出すことができます。

これで、記事表示部分に

と書けば、$parentに最上層カテゴリーの「表示名」が入ります。
echoで表示するなり、条件分岐に使用するなどします。

説明

get_category_parents()は、指定した区切り文字で最上層からのカテゴリー一覧を取得する関数です。
主にパンくずリストなどで使用されるものですが、二番目の引数をfalseにするとリンクなしで表示名だけ取得できます。

カンマ区切りで取得したら、PHPコアのexplode()で配列に変換し、最上層になっているはずの、最初の値を返します。

表示部分に書かれている、attribute_escape()とは、<やら>やらのパースエラーを引き起こすタグを除去するWordPressの汎用関数です。
条件分岐のキーにする場合は必要ないかもしれませんが、echoで出力する場合、テーマを配布する場合は念のため入れておいた方がいいと思います。

参考:Yuriko.Net » HTML エスケープなしの出力は怖い

2-b. IDを取得する方法

以下の関数をテーマファイル内に追加します。

こういったユーザー関数は記事表示部分ではなく、テーマファイル「functions.php」に追加してください。あとで何度でも呼び出すことができます。

これで、記事表示部分に

と書けば、$parentに最上層カテゴリーの「ID」が入ります。
echoで表示するなり、条件分岐に使用するなどします。
IDは必ず数値が返るため直感的ではないですが、安全性を重視するならこちらの方が良いかもしれません。

説明

ひとつ上のカテゴリーIDを取得するget_category_parent()を、get_category_top()内で繰り返すことで、いちばん上のIDを取り出しています。

上のカテゴリーが見つからなくなる(0が返ります)か、
5階層上まで処理を繰り返します。
5階層もあるカテゴリーなんかありえないのですが、データベースやサーバーの不具合で無限ループが起こらないように念のため保険をかけています。


階層カテゴリー情報は頻繁に利用されるのに、あまり関数が用意されていません :(
海外のCodexには掲載されているのかもしれませんが、WordPressの内部を直接見てみてもそれらしいものはないようです。
いずれにしてもコア関数は自由度を上げるために引数が多くなっている傾向があるので、IDを取得するだけなら、自分で関数を書いてしまった方が処理が早そうです。

私はまだプログラミングに詳しくないので、
もっと良い方法があれば教えてください><


TwitterTwitterで記事を紹介して下さい(-人-)

Back to top

3 Comments

R-STYLE

Comment

どうも。
似非プログラマが来ました!

2つ目の関数は以下のように書けばスッキリしますね。
function get_category_top($ID) {
$parent = get_category_parent($ID);
for ($i = 0; $i < 5; $i++) {
$parentID = get_category_parent($parent);
if(!$parentID) {return $parent;}
$parent = $parentID;
}
}

少し解説すると、まずwhileブロック内の2つ目のif文はfor文を使えば不要です。
1つ目のif文は条件がfalseの場合はreturnしているので、条件を逆にしてその場でreturnしてしまいます。
continue, break, return等はなるべく上の方に書いて以降の処理をしない方が良いですし、そうする事でelseブロックを使わずに書けてスッキリします。
ちなみに、returnは関数ブロックを抜けるので、returnの後にbreakは不要です。

ただ、上の例ではループを抜けた場合の動きが不明なので、恐らく以下の方が良いのではないでしょうか。
多少仕様が変わってしまいますし、PHPに詳しい方ならどう言うかは分かりませんが…

function get_category_top($ID) {
$parent = get_category_parent($ID);
for ($i = 0; $i < 5; $i++) {
$parentID = get_category_parent($parent);
if(!$parentID) {break;}
$parent = $parentID;
}
return $parent;
}

  • by: R-STYLE
  • time: 2009.04.09 16:01:03
WebbingStudio

Comment

こんにちは。アドバイスありがとうございます!

return以降は、そこでループが終了するのですか…
条件を反転して考えるというのも必要なんですね。

あと、twitterでも補足ありがとうございます!

> コメントに書き忘れましたが、
> 1つ目の関数は

> return get_category($ID)->category_parent;

> の1行で書きたいですね。

自分はチキンなので、いちいち配列の宣言やif / elseの条件分岐を書いてしまう癖があります。
そこを整理すればもっと短い構文が書けそうですね。

shun

Comment

参考になりました、ありがとうございます!

2-b を再帰処理にしてみました。

function get_root_category_id($ID){
$parent = get_category($ID)->category_parent;

if($parent != 0){
return get_root_category_id($parent);
} else {
return $ID;
}
}

  • by: shun
  • time: 2009.09.22 07:16:05
Trackback URL

コメントをどうぞ

About me
うぇびん
Author
うぇびん
Location
Sapporo,Hokkaido
Birth
March 26,1975

フリーのWeb屋です。
主に、各種CMSのデザインカスタマイズを請け負っています。制作会社様への技術提供もやってます。
WebbingStudioは屋号です。ウェビングスタジオとお読みくださいまし。

Archive

pagetop

[No IE6!] このウェブサイトは、InternetExplorer6以前では透過画像などに不具合が生じます。