トップ
【WP】目次を自作で作る

WordPressでブログを書いて情報発信している会社は多いと思います。
いろんなブログを見に行ってる時に、記事ページはやっぱり目次があったほうが見やすいなと思いました。
プラグインでもいいんですが、サイトによっては重くなったりするし、コンフリクトのリスクもあります。
phpなんとなくわかるんだったら、書いた方が軽いので色々検索して合体させました。
プラグインの場合
有名どころはEasy Table of Contentsです。
入れるだけで文字くを作ってくれます。
サクッとやりたい方はこれをインストールして有効にしてください。
自作の場合
function.phpにコードを書いて動かします、function.phpを触ると危ないからバックアップを!
といった記載をよく見ますが、個人的には思っていません。
どこを触ったか覚えていればいいんです。
どんな仕組み?
ざっくり言うと、「記事内のコードを見て、h2とh3があればアンカーを作って表示する」
と言うプログラムです。
the_content内のタグをpreg_matchで検索、h2とh3があれば、それをアンカータグにして、かつそれぞれに対応するidを振ってくれます。
h2の数で発動管理もできますし、囲むタグも自分で指定できます。
注意点としては、記事内のh2とh3にクラスがついていると発動しないところです。
function.php
function my_add_content( $content ) {
if ( is_single() ) {
$pattern = '/<h[2-3]>(.*?)<\/h[2-3]>/i'; // 属性を持たないh2・h3要素を正規表現で表すパターン
preg_match_all( $pattern, $content, $matches, PREG_SET_ORDER ); // 本文の中から、すべてのh2・h3要素を検索
// ページ内のh2・h3要素が3つ以上の場合に目次を出力
if( count( $matches ) > 1 ){
$toc = '<div class="toc_wrap"><h2 class="twt">目次</h2><ol class="olw">';
$hierarchy = NULL;
$i = 0;
// 本文内のh2・h3要素を上から順番にループで処理
foreach( $matches as $element ){
$i++;
$id = 'chapter-' . $i;
$chapter = preg_replace( '/<(.+?)>(.+?)<\/(.+?)>/', '<$1 id ="' . $id . '">$2</$3>', $element[0] );
$content = preg_replace( $pattern, $chapter, $content, 1);
if( strpos( $element[0], '<h2' ) === 0 ){
$level = 0;
}else{
$level = 1;
}
if( $hierarchy === $level ){
$toc .= '</li>';
}elseif( $hierarchy < $level ){
$toc .= '<ol class="oli">';
$hierarchy = 1;
}elseif( $hierarchy > $level ){
$toc .= '</li></ol></li>';
$hierarchy = 0;
}elseif( $i == 1 ){
$hierarchy = 0;
}
$title = $element[1];
$toc .= '<li><a href="#' . $id . '">' . $title . '</a>';
}
if( $level == 0 ){
$toc .= '</li></ol>';
}elseif( $level == 1 ){
$toc .= '</li></ol></li></ol>';
}
$toc .= '</div>';
//ナビを出す場所の指定(1個目のh2の下に出す)
$h2 = '/^<h2.*?>.+?<\/h2>$/im';//H2見出しのパターン
if ( preg_match_all( $h2, $content, $h2s )) {
if ( $h2s[0] ) {
if ( $h2s[0][0] ) {//1番目のH2見出し手前に挿入
$content = str_replace($h2s[0][0], $toc.$h2s[0][0], $content);
}
}
}
}
}
return $content;
}
add_filter( 'the_content', 'my_add_content' );
コピペでいけると思います。
細かい説明は参考引用のリンクから見に行ってください!
参考引用:コード全体
参考引用2:出す場所の指定