株式会社アドベンチャーのフロントエンド@a-yamamotoです。
特にフロントネタが思いつかなかったので、先日wordpressいじってて困ったことでも備忘録として残しておこうと思います。
欲しいカテゴリが取れない問題
キレイにカテゴリ作っても、記事を書く人によってカテゴリの付け方が微妙に違ったりするんですよね。
もしくは後からカテゴリが増えて付け方が変わっちゃったとか。
どういう事かと言いますと・・・
カテゴリ1つの場合
これはカテゴリ取得しても当然1つしかないので、よく見る↓のコードで十分。
$category = get_the_category();
$cat_name = $category[0]->cat_name;
丁寧にツリーの頭から選んだ場合は?
先ほどのコードを使っても $category[0] に 上野 が入るとは限らないんですよね。
そもそも get_the_category() でカテゴリを取得した時、4つのカテゴリがどういう順で入るのかは、WP次第らしいです。
なので、本来は上のコードで賄えてたはずなのに、気づけば中階層の微妙なカテゴリが表示されてるなんてことが。。
一番下のやつでいんだけど!なんで親から順番に取ってくれないの!
って数年前も同じこと思った気がするけど、ここの仕様は変わらないのかしら。
最下層カテゴリを取得する
そんな時は↓をfunction.phpにペッ。
function get_lowest_category ($sbjcat = '', $taxonomy = 'category') {
$terms = get_the_terms($sbjcat, $taxonomy);
if (empty($terms)) return false;
$candidate = $terms;
$cnt = count($terms);
if ($cnt > 1) {
foreach ($terms as $key => $term) {
foreach ($terms as $term2) {
if (term_is_ancestor_of($term->term_id, $term2->term_id, $taxonomy)) {
unset($candidate[$key]);
break;
}
}
}
}
return $candidate;
}
これで最下層のカテゴリが取れる。
別のツリーのカテゴリも選んでたらどうなるの
こういうパターン。あるある。
これも先ほどの関数を使って最下層のカテゴリを取得。
$category = get_lowest_category();
そうすると $category の中に、それぞれの最下層である 上野 と 和食が入ります。
で、ここでまた問題発生。
この場合、最終的にはどちらが出力されるのか。
これも結局WP次第。
ツリーに優先順位をつけてみる
こういう時用にツリーに優先順位をつけることにしました。
複数あった場合、国内 > ジャンル になるように。
なのでこの場合は最終的に 上野 がとれるのが正解。
なので今度は最上層のカテゴリ情報が必要になります。
function.phpにこちらもペッ。
/* 最上層のカテゴリ取得 */
function get_top_category ($sbjcat = '', $taxonomy = 'category') {
if (empty($sbjcat) && is_category()) {
$sbjcat = get_query_var('cat');
} elseif (empty($sbjcat) && is_tax()) {
$sbjcat = get_query_var('term_id');
$taxonomy = get_query_var('taxonomy');
} elseif (!is_numeric($sbjcat)) {
$sbjcat = get_term_by('slug', $sbjcat, $taxonomy)->term_id;
}
if (!$sbjcat) return false;
$ancestors = array_reverse(get_ancestors($sbjcat , $taxonomy));
if(isset($ancestors[0])) $ancestor_id = $ancestors[0]; else $ancestor_id = $sbjcat;
return get_term($ancestor_id , $taxonomy);
}
最下層カテゴリが複数あったら、国内 > ジャンル になるように並び替え。
$descends = get_lowest_category();
$cnt = count($descends);
$cate_ary = array();
if ($cnt > 1) {
$order = [japan, genre]; // 左から優先度高
foreach($descends as $descend) {
$slug = $descend->slug;
$ancestor = get_top_category($slug);
$parent = $ancestor->slug; // ツリーの最上層のカテゴリ
$descend->group_parent = $parent;
array_push($cate_ary, $descend);
}
usort($cate_ary, function($x, $y) use ($order){
return array_search($x->group_parent, $order) > array_search($y->group_parent, $order);
});
$item = $cate_ary[0];
} else {
foreach($descends as $descend) {
$item = $descend;
}
}
先頭のデータをとれば、ちょっと無理やり感あるけど 上野 がとれるようになりました。
まとめ
そもそも、この記事にはこのカテゴリ表示!みたいのがあるといいんだけど。
もっといいやり方ないかしら。