前回のパラメータでカスタマイズしやすいWordPressのページナビを作ってみたに続き、パンくずナビも作ってみました。
カスタム投稿タイプの年月アーカイブとか、カスタム投稿タイプの寄稿者など複合条件までは対応できていませんが、カスタム投稿タイプ、カスタムタクソノミー、フロントページの表示設定など、多彩な設定に対応できています。
[2011.06.30追記]
プラグイン版を公開いたしました。一部修正してありますので、こちらをご利用ください。
導入方法
- 使っているテーマのfunctions.phpにCODE 1を、ページナビを使っていない方は、CODE 2も追記してください。あるいは、独自プラグインにしてしまってもいいです。(独自プラグインの作り方は、初心者でも10秒でできる WordPress プラグインの作り方やWordPress でスニペットを簡単に管理する方法あたりを参考に)
- テーマファイルのページナビを表示したい位置に
<?php bread_crumb(); ?>
を追加してください。
これだけでも一応は、表示されるようになりますが、いくつかのパラメータで表示方法を変更することができます。
指定可能なパラメータ
- type
- stringを指定すると、リストではなく文字列として出力します。デフォルトはlist
- home_label
- トップページの表示テキスト。デフォルトは「トップページ」
- search_label
- 検索結果の表示テキスト。デフォルトは「『%s』の検索結果」(%sが検索文字列)
- 404_label
- 404ページの表示テキスト。デフォルトは「404 Not Found」
- category_label
- カテゴリーの表示テキスト。デフォルトは「%s」(%sがカテゴリー名)
- tag_label
- 投稿タグの表示テキスト。デフォルトは「%s」(%sが投稿タグ名)
- taxonomy_label
- カスタムタクソノミーの表示テキスト。デフォルトは「%s」(%sがタクソノミー名)
- author_label
- 寄稿者の表示テキスト。デフォルトは「%s」(%sが寄稿者名)
- attachment_label
- アタッチメントの表示テキスト。デフォルトは「%s」(%sがアタッチメント名)
- year_label
- 年の表示テキスト。デフォルトは「%s年」(%sが年の数字)
- month_label
- 月の表示テキスト。デフォルトは「%s月」(%sが月の数字)
- day_label
- 日の表示テキスト。デフォルトは「%s日」(%sが日の数字)
- joint_string
- typeでstringを指定した場合の結合文字列。デフォルトは「>」(>)
- navi_element
- ラッパー要素名。divまたはnavを選択可能。デフォルトは空(要素無し)
- elm_class
- ラッパー要素のクラス名。ラッパー要素がなくタイプがリストの場合は、ulのクラス名となる。デフォルトは、「bread_crumb」
- elm_id
- ラッパー要素のid名。ラッパー要素がなくタイプがリストの場合は、ulのid名となる。デフォルトは、空。(idなし)
- li_class
- タイプがリストの場合のliに付くクラス名。デフォルトは空(なし)
- class_prefix
- 各クラスに付く接頭辞。デフォルトは空(なし)
- current_class
- 表示中のページのパンくずナビに付与されるクラス名。デフォルトは「current」
- indent
- タブでのインデント数。デフォルトは0。
- echo
- 出力を行うか。デフォルトはtrue(出力する)。0またはfalseの指定でPHPの値としてreturnする。
CODE 1
function bread_crumb( $args = '' ) { $default = array( 'type' => 'list', 'home_label' => 'トップページ', 'search_label' => '『%s』の検索結果', '404_label' => '404 Not Found', 'category_label' => '%s', 'tag_label' => '%s', 'taxonomy_label' => '%s', 'author_label' => '%s', 'attachment_label' => '%s', 'year_label' => '%s年', 'month_label' => '%s月', 'day_label' => '%s日', 'joint_string' => ' > ', 'navi_element' => '', 'elm_class' => 'bread_crumb', 'elm_id' => '', 'li_class' => '', 'class_prefix' => '', 'current_class' => 'current', 'indent' => 0, 'echo' => true, ); $default = apply_filters( 'bread_crumb_default', $default ); $args = wp_parse_args( $args, $default ); $elm = in_array( $args['navi_element'], array( 'nav', 'div', '' ) ) ? $args['navi_element'] : 'div'; $args['elm_id'] = is_array( $args['elm_id'] ) ? $default['elm_id'] : $args['elm_id']; $args['elm_id'] = preg_replace( '/[^\w_-]+/', '', $args['elm_id'] ); $args['elm_id'] = preg_replace( '/^[\d_-]+/', '', $args['elm_id'] ); $args['class_prefix'] = is_array( $args['class_prefix'] ) ? $default['class_prefix'] : $args['class_prefix']; $args['class_prefix'] = preg_replace( '/[^\w_-]+/', '', $args['class_prefix'] ); $args['class_prefix'] = preg_replace( '/^[\d_-]+/', '', $args['class_prefix'] ); $args['elm_class'] = sanitize_attr_classes( $args['elm_class'], $args['class_prefix'] ); $args['li_class'] = sanitize_attr_classes( $args['li_class'], $args['class_prefix'] ); $args['current_class'] = sanitize_attr_classes( $args['current_class'], $args['class_prefix'] ); $args['current_class'] = $args['current_class'] ? $args['current_class'] : $args['class_prefix'] . $default['current_class']; $tabs = str_repeat( "\t", (int)$args['indent'] ); $bread_crumb_arr = get_bread_crumb_array( $args ); $elm_attrs = ''; if ( $args['elm_id'] ) { $elm_attrs = ' id="' . $args['elm_id'] . '"'; } if ( $args['elm_class'] ) { $elm_attrs .= ' class="' . $args['elm_class'] . '"'; } $output = ''; $elm_tabs = ''; $output = ''; if ( $elm ) { $elm_tabs = "\t"; $output = $tabs . '<' . $elm; if ( $elm_attrs ) { $output .= $elm_attrs . ">\n"; } } if ( $args['type'] == 'string' ) { $output = array(); $cnt = 1; foreach ( $bread_crumb_arr as $ancestor ) { if ( $cnt == count( $bread_crumb_arr ) ) { $output[] = '<strong class="' . $args['current_class'] . '">' . apply_filters( 'the_title', $ancestor['title'] ) . '</strong>'; } else { $output[] = '<a href="' . $ancestor['link'] . '">' . apply_filters( 'the_title', $ancestor['title'] ) . '</a>'; } $cnt++; } $output = $elm_tabs . $tabs . implode( esc_html( $args['joint_string'] ), $output ); $output = apply_filters( 'bread_crumb_after', $output, $args ); } else { $output .= $elm_tabs . $tabs . '<ul'; if ( ! $elm && $elm_attrs ) { $output .= $elm_attrs; } $output .= ">\n"; $output = apply_filters( 'bread_crumb_before', $output, $args ); $cnt = 1; foreach ( $bread_crumb_arr as $ancestor ) { $classes = array(); $classes[] = $args['class_prefix'] . 'level-' . $cnt; if ( $cnt == 1 ) { $classes[] = $args['class_prefix'] . 'top'; } else { $classes[] = $args['class_prefix'] . 'sub'; } if ( $cnt == count( $bread_crumb_arr ) ) { $classes[] = $args['class_prefix'] . 'tail'; $output .= $elm_tabs . $tabs . ' <li class="' . implode( ' ', $classes ); if ( $args['li_class'] ) { $output .= ' ' . $args['li_class']; } $output .= ' ' . $args['current_class']; $output .= '">' . apply_filters( 'the_title', $ancestor['title'] ) . '</li>' . "\n"; } else { $output .= $elm_tabs . $tabs . ' <li class="' . implode( ' ', $classes ); if ( $args['li_class'] ) { $output .= ' ' . $args['li_class']; } $output .= '"><a href="' . $ancestor['link'] . '">' . apply_filters( 'the_title', $ancestor['title'] ) . '</a></li>' . "\n"; } $cnt++; } $output = apply_filters( 'bread_crumb_after', $output, $args ); $output .= $elm_tabs . $tabs . '</ul>' . "\n"; } if ( $elm ) { $output .= $tabs . '</' . $elm . ">\n"; } $output = apply_filters( 'bread_crumb', $output, $args ); if ( $args['echo'] ) { echo $output; } else { return $output; } } function get_bread_crumb_array( $args ) { global $post; $bread_crumb_arr = array(); $bread_crumb_arr[] = array( 'title' => $args['home_label'], 'link' => get_bloginfo( 'url' ) . '/' ); $bread_crumb_arr = add_posts_page_array( $bread_crumb_arr ); if ( is_404() ) { $bread_crumb_arr[] = array( 'title' => $args['404_label'], 'link' => false ); } elseif ( is_search() ) { $bread_crumb_arr[] = array( 'title' => sprintf( $args['search_label'], get_search_query() ), 'link' => false ); } elseif ( is_tax() ) { $taxonomy = get_query_var( 'taxonomy' ); $term = get_term_by( 'slug', get_query_var( 'term' ), $taxonomy ); if ( is_taxonomy_hierarchical( $taxonomy ) && $term->parent != 0 ) { $ancestors = array_reverse( get_ancestors( $term->term_id, $taxonomy ) ); foreach ( $ancestors as $ancestor_id ) { $ancestor = get_term( $ancestor_id, $taxonomy ); $bread_crumb_arr[] = array( 'title' => $ancestor->name, 'link' => get_term_link( $ancestor, $term->slug ) ); } } $bread_crumb_arr[] = array( 'title' => sprintf( $args['taxonomy_label'], $term->name ), 'link' => get_term_link( $term->term_id, $term->slug ) ); } elseif ( is_attachment() ) { if ( $post->post_parent ) { if ( $parent_post = get_post( $post->post_parent ) ) { $singular_bread_crumb_arr = get_singular_bread_crumb_array( $parent_post ); $bread_crumb_arr = array_merge( $bread_crumb_arr, $singular_bread_crumb_arr ); } } $bread_crumb_arr[] = array( 'title' => $parent_post->post_title, 'link' => get_permalink( $parent_post->ID ) ); $bread_crumb_arr[] = array( 'title' => sprintf( $args['attachment_label'], $post->post_title ), 'link' => get_permalink( $post->ID ) ); } elseif ( is_singular() && ! is_front_page() ) { $singular_bread_crumb_arr = get_singular_bread_crumb_array( $post ); $bread_crumb_arr = array_merge( $bread_crumb_arr, $singular_bread_crumb_arr ); $bread_crumb_arr[] = array( 'title' => $post->post_title, 'link' => get_permalink( $post->ID ) ); } elseif ( is_category() ) { global $cat; $category = get_category( $cat ); if ( $category->parent != 0 ) { $ancestors = array_reverse( get_ancestors( $category->term_id, 'category' ) ); foreach ( $ancestors as $ancestor_id ) { $ancestor = get_category( $ancestor_id ); $bread_crumb_arr[] = array( 'title' => $ancestor->name, 'link' => get_category_link( $ancestor->term_id ) ); } } $bread_crumb_arr[] = array( 'title' => sprintf( $args['category_label'], $category->name ), 'link' => get_category_link( $cat ) ); } elseif ( is_tag() ) { global $tag_id; $tag = get_tag( $tag_id ); $bread_crumb_arr[] = array( 'title' => sprintf( $args['tag_label'], $tag->name ), 'link' => get_tag_link( $tag_id ) ); } elseif ( is_author() ) { $author = get_query_var( 'author' ); $bread_crumb_arr[] = array( 'title' => sprintf( $args['author_label'], get_author_name( get_query_var( 'author' ) ) ), 'link' => get_author_posts_url( $author ) ); } elseif ( is_day() ) { $year = get_query_var( 'year' ); $month = get_query_var( 'monthnum' ); $day = get_query_var( 'day' ); $bread_crumb_arr[] = array( 'title' => sprintf( $args['year_label'], $year ), 'link' => get_year_link( $year ) ); $bread_crumb_arr[] = array( 'title' => sprintf( $args['month_label'], $month ), 'link' => get_month_link( $year, $month ) ); $bread_crumb_arr[] = array( 'title' => sprintf( $args['day_label'], $day ), 'link' => get_day_link( $year, $month, $day ) ); } elseif ( is_month() ) { $year = get_query_var( 'year' ); $month = get_query_var( 'monthnum' ); $bread_crumb_arr[] = array( 'title' => sprintf( $args['year_label'], $year ), 'link' => get_year_link( $year ) ); $bread_crumb_arr[] = array( 'title' => sprintf( $args['month_label'], $month ), 'link' => get_month_link( $year, $month ) ); } elseif ( is_year() ) { $year = get_query_var( 'year' ); $bread_crumb_arr[] = array( 'title' => sprintf( $args['year_label'], $year ), 'link' => get_year_link( $year ) ); } return $bread_crumb_arr; } function get_singular_bread_crumb_array( $post ) { $bread_crumb_arr = array(); $post_type = $post->post_type; if ( is_post_type_hierarchical( $post_type ) ) { $ancestors = array_reverse( get_post_ancestors( $post ) ); if ( count( $ancestors ) ) { $ancestor_posts = get_posts( 'post_type=' . $post_type . '&include=' . implode( ',', $ancestors ) ); foreach( $ancestors as $ancestor ) { foreach ( $ancestor_posts as $ancestor_post ) { if ( $ancestor == $ancestor_post->ID ) { $bread_crumb_arr[] = array( 'title' => $ancestor_post->post_title, 'link' => get_permalink( $ancestor_post->ID ) ); } } } } } else { $post_type_taxonomies = get_object_taxonomies( $post_type, false ); if ( is_array( $post_type_taxonomies ) && count( $post_type_taxonomies ) ) { foreach( $post_type_taxonomies as $tax_slug => $taxonomy ) { if ( $taxonomy->hierarchical ) { $terms = get_the_terms( $post->ID, $tax_slug ); if ( $terms ) { $term = array_shift( $terms ); if ( $term->parent != 0 ) { $ancestors = array_reverse( get_ancestors( $term->term_id, $tax_slug ) ); foreach ( $ancestors as $ancestor_id ) { $ancestor = get_term( $ancestor_id, $tax_slug ); $bread_crumb_arr[] = array( 'title' => $ancestor->name, 'link' => get_term_link( $ancestor, $tax_slug ) ); } } $bread_crumb_arr[] = array( 'title' => $term->name, 'link' => get_term_link( $term, $tax_slug ) ); break; } } } } } return $bread_crumb_arr; } function add_posts_page_array( $bread_crumb_arr ) { if ( is_page() || is_front_page() ) { return $bread_crumb_arr; } elseif ( is_category() ) { $tax = get_taxonomy( 'category' ); if ( count( $tax->object_type ) != 1 || $tax->object_type[0] != 'post' ) { return $bread_crumb_arr; } } elseif ( is_tag() ) { $tax = get_taxonomy( 'post_tag' ); if ( count( $tax->object_type ) != 1 || $tax->object_type[0] != 'post' ) { return $bread_crumb_arr; } } elseif ( is_tax() ) { $tax = get_taxonomy( get_query_var( 'taxonomy' ) ); if ( count( $tax->object_type ) != 1 || $tax->object_type[0] != 'post' ) { return $bread_crumb_arr; } } elseif ( is_home() && ! get_query_var( 'pagename' ) ) { return $bread_crumb_arr; } else { $post_type = get_query_var( 'post_type' ) ? get_query_var( 'post_type' ) : 'post'; if ( $post_type != 'post' ) { return $bread_crumb_arr; } } if ( get_option( 'show_on_front' ) == 'page' && $posts_page_id = get_option( 'page_for_posts' ) ) { $posts_page = get_post( $posts_page_id ); $bread_crumb_arr[] = array( 'title' => $posts_page->post_title, 'link' => get_permalink( $posts_page->ID ) ); } return $bread_crumb_arr; }
CODE 2
CODE 2も必要ではありますが、パラメータでカスタマイズしやすいWordPressのページナビを作ってみたでも使っているものなので、ページナビのコードを使っている方は、CODE 2を追加する必要はありません。
function sanitize_attr_classes( $classes, $prefix = '' ) { if ( ! is_array( $classes ) ) { $classes = preg_replace( '/[^\s\w_-]+/', '', $classes ); $classes = preg_split( '/[\s]+/', $classes ); } foreach ( $classes as $key => $class ) { if ( is_array( $class ) ) { unset( $classes[$key] ); } else { $class = preg_replace( '/[^\w_-]+/', '', $class ); $class = preg_replace( '/^[\d_-]+/', '', $class ); if ( $class ) { $classes[$key] = $prefix . $class; } } } $classes = implode( ' ', $classes ); return $classes; }
パンくずナビで出力されるHTMLソース
リスト形式
<ul class="bread_crumb"> <li class="level-1 top"><a href="http://www.example.com/">トップページ</a></li> <li class="level-2 sub"><a href="http://www.example.com/category/honda/">HONDA</a></li> <li class="level-3 sub"><a href="http://www.example.com/category/honda/sports/">スポーツ</a></li> <li class="level-4 sub"><a href="http://www.example.com/category/honda/sports/coupe/">クーペ</a></li> <li class="level-5 sub tail current">インテグラ</li> </ul>
文字列形式
<a href="http://www.example.com/">トップページ</a> > <a href="http://www.example.com/category/honda/">HONDA</a> > <a href="http://www.example.com/category/honda/sports/">スポーツ</a> > <a href="http://www.example.com/category/honda/sports/coupe/">クーペ</a> > <strong class="current">インテグラ</strong>
「パラメータでカスタマイズしやすいWordPressのパンくずナビを作ってみた」への2件のフィードバック