読者です 読者をやめる 読者になる 読者になる

渡米生活。(日記)

渡米生活。本家から切り離しました。あまり渡米生活に関係のないプログラムネタや音楽ネタなど。

カテゴリー一覧ページで現在のカテゴリーの情報(スラッグ、IDなど)を取得する方法

カテゴリー表示ページで、カテゴリーごとにサイドバーを変えたい、とかいう際に、is_category関数で分岐したりしますが、これがうまく動かないことがあります。
たとえば、カテゴリーが入れ子になっている場合で、子カテゴリの記事一覧を表示すると、is_category関数には親カテゴリのスラッグしか指定していないため、if文でうまく分岐できずにデフォルトのサイドバーが使われてしまう、といった感じです。
まあ、表示される可能性があるカテゴリのスラッグを、片っ端からis_category関数の引数に登録すればよい話ですが、子カテゴリが新しく増える度にcategory.phpを書き換えるのは管理上あまり好ましくないですね。

それで、自前で関数を書き、カテゴリー全階層をサーチするようにしたのですが、何故かこれがうまく動かないケースがあり、ずっと対処療法で誤摩化していました。
で、よくよくマニュアルを見たら、自前関数の中で、こいつを使っていたのがまずかったらしい。

$cat=get_category_by_slug($catslag);

どうやら、カテゴリをとってくる系の関数は、ループの中でしかまともに動かないらしのですね。($postグローバル変数が書き変わると誤作動する)

それで、カテゴリー表示ページ(category.phpが表示するページ)で現在表示しているカテゴリーの情報を保存したオブジェクトをとってこようとgoogle様にお尋ねしたら、結構面倒くさいようなことが書いてある。

ちょっと挫折しかけましたが、いやまてよ、is_category関数はカテゴリー表示ページならどこでも使えるんだから、どっかに情報は保存されているはずだ! と思い、query.phpの中のis_category関数を眺めると、要はcategory.phpの中で、次のようにやれば現在のカテゴリの情報は何でもとってこられる模様。

<?php 

   // 現在のグローバルクエリを取得
   global $wp_query;

   // 直前のクエリーオブジェクトを取得
   $cat_obj = $wp_query->get_queried_object();

  // 欲しい情報を取得

   // 現在表示中のカテゴリーID
   $catid = $cat_obj->term_id

   // 現在表示中のカテゴリーのスラッグ
   $catslag = $cat_obj->slag

?>

これだと、Loopの中であろうがなかろうが、まともな情報をとってきてくれる模様です。
というのは、is_category関数はLoopの中で使用せよ、等の制限がないからで、つまり、$wp_queryグローバルオブジェクトは、少なくともカテゴリー一覧ページ表示中には書き変わらんのだろう、と期待したのですが…
本当のところはどうなのか分かりません(笑)。
(まあ、うちではまともに動いているので、これで良いのだと思う)
ちなみに、カテゴリーオブジェクトからこのほかにどんな情報を引き出せるかは、以下のページの戻り値の項目をご覧下さい。

WordPress 私的マニュアル
http://elearn.jp/wpman/function/get_category.html


というわけで、冒頭の問題の対策として、こんなコードを書いてみました。

<?php 


   // 現在のグローバルクエリを取得
   global $wp_query;

   // 直前のクエリーオブジェクトを取得
   $cat_obj = $wp_query->get_queried_object();

   // 以下は自前の関数、カテゴリが入れ子になっている場合に
   // 一番親のカテゴリオブジェクトをとってくる。
   $topmost_cat = hmo_get_category_ancestor($cat_obj);

   //デバッグしたい方は以下のコメントアウトを外して下さい。
   //print "current category is ".$cat_obj->slug . "<br>";
   //print "current topmost category is ".$topmost_cat->slug . "<br>";

   // あとは、一番上のカテゴリのスラッグやIDで分岐
   if ($topmost_cat->slug == 'works') { 
      get_sidebar('works');                        
                                                   
   } elseif ($topmost_cat->slug == 'archives') {   
      get_sidebar('archives');  
                   
   } else {
      get_sidebar();
   }
...

?>

hmo_get_category_ancesterは、カテゴリが入れ子構造になっているときに、一番親のカテゴリをとってくる関数です。これをやらないと、$wp_queryに子カテゴリの情報が入ってる場合に、if文でスルーしてしまうので。
こんな感じで、function.phpに書いておきます。

/**
 * get ancester of current category
 *
 * @since HMO 0.1:
 */
if ( ! function_exists( 'hmo_get_category_ancestor' ) ) :
function hmo_get_category_ancestor($cat) {
   while ($cat->parent != 0) {
      $cat = get_category($cat->parent);
   }
   return $cat;
}
endif;

これで、一番上のカテゴリごとに違うサイドバーを設定できました。