パーマリンク設定で複数カテゴリーを使う場合に自分が選んだカテゴリを表示させる
wordpressパーマリンク設定で、%category%/%postname% みたいなことをやっていると、カテゴリが複数登録された記事の場合、勝手にカテゴリーIDの一番小さいものを選んで使用します。
カテゴリーが子カテゴリを持っていて、どっちにも登録したいような場合、カテゴリIDの大小によって親カテゴリが使われたり子カテゴリが使われたり、といった感じで統一感に欠けた振る舞いになります。
ページのURL階層のように、常に一番深い階層を使うか、あるいは常に親カテゴリを使うか、どっちかに統一して欲しいわけです。
しかし、カテゴリーIDは勝手に変更できない。(まあ、データベースを弄っちゃう、という荒技もあるけど)
というわけで、これを、自分の選んだカテゴリで表示するよう変更するためのフィルターフックを書いてみました。
- 記事のpost_metaに、permalink_cat_idというキーでカテゴリIDが登録されていた場合は、それを使う
- permalink_cat_idフィールドが空の場合もしくはそもそも登録されていない場合は、wordpressのデフォルトの表記に従う(つまりカテゴリIDが一番小さなものが使われる)
というような振る舞いです。
post_metaにカテゴリIDを登録する方法は色々ありますが、私はCustom Field Gui Utilityというプラグインを使わせてもらっています。
ちなみに、お目当てのカテゴリIDを知るには、カテゴリ編集ページに行って、URLを見ると埋め込まれています。
もっとも、私はAdminerというプラグインを入れて、直接データベースを見に行ってますが。
カテゴリIDの代わりにカテゴリスラッグを使う、というのも考えたのですが、ただでさえフックかけてコスト高いのに、あんまり重い作業をさせるのは嫌だな、と思って止めました。(自分結構スラッグ変更するし)
一度設定したスラッグは絶対変えない、というSEO達人の皆様は、そのへん仕様変更されたら良いと思います。
関数はほとんどget_permalink関数上書きに近いですが、こんな感じ。
あんまりphpは書き慣れてないので、あまりスマートなコードではないかも。
動作確認きちんとやってませんので、ご使用は自己責任でお願いします。
/** * 記事に複数カテゴリを登録し、パーマリンクが * %category%/%postname% の場合に自分で選んだカテゴリで * 表示させる */ function hmo_modify_permalink($permalink, $post, $leavename) { /* 書き換えの必要がない場合は即関数を抜ける */ if ( empty($post->ID) || $post->post_type == 'page' || $post->post_type == 'attachment' || in_array($post->post_type, get_post_types( array('_builtin' => false) ) ) ) { return $permalink; } /* post_metaのparmalink_cat_idにカテゴリIDが登録されていない場合 は、デフォルトのパーマリンクを使う */ $permalink_cat_id = ''; $permalink_cat_id = get_post_meta($post->ID, 'permalink_cat_id', true); if ($permalink_cat_id == '') { return $permalink; } /* パーマリンク作成、以下はほとんど wp-include/link-template.php のget_permalink関数のコピー */ $rewritecode = array( '%year%', '%monthnum%', '%day%', '%hour%', '%minute%', '%second%', $leavename? '' : '%postname%', '%post_id%', '%category%', '%author%', $leavename? '' : '%pagename%', ); $permalink_str = get_option('permalink_structure'); if ( '' != $permalink_str && !in_array($post->post_status, array('draft', 'pending', 'auto-draft')) ) { $unixtime = strtotime($post->post_date); $category = ''; if ( strpos($permalink_str, '%category%') !== false ) { /* post_metaのparmalink_cat_idに登録されたidの カテゴリを使う */ if ( $permalink_cat = get_category($permalink_cat_id) ) { $category = $permalink_cat->slug; if ( $parent = $permalink_cat->parent ) { $category = get_category_parents($parent, false, '/', true) . $category; } } // show default category in permalinks, without // having to assign it explicitly if ( empty($category) ) { $default_category = get_category( get_option( 'default_category' ) ); $category = is_wp_error( $default_category ) ? '' : $default_category->slug; } } $author = ''; if ( strpos($permalink_str, '%author%') !== false ) { $authordata = get_userdata($post->post_author); $author = $authordata->user_nicename; } $date = explode(" ",date('Y m d H i s', $unixtime)); $rewritereplace = array( $date[0], $date[1], $date[2], $date[3], $date[4], $date[5], $post->post_name, $post->ID, $category, $author, $post->post_name, ); /* get_permalink関数で生成した $permalinkをここで上書き */ $permalink = home_url( str_replace($rewritecode, $rewritereplace, $permalink_str) ); $permalink = user_trailingslashit($permalink, 'single'); } return $permalink; } /*テンプレートタグの <?php get_permalink() > が返すリンクを 上書きするフックをかける*/ add_filter( 'post_link', 'hmo_modify_permalink', 10, 3 );
以上。
このコードをfunction.phpに書いておけば、で生成されるパーマリンクが上記の仕様で変更(上書き)されます。