当記事ではPHPを使用して見出しから目次を自動生成する方法について記します。
目次の自動生成はJavascriptで行うのが一般的かもしれませんが、PHPの方がJavascriptで実装するよりもページの表示速度が向上するメリットがあります。
複数階層の見出しにも対応できるように実装していきましょう。
やりたいこと
今回実現したい事のおさらいをしておきましょう。
下記のようなHTMLがある時に、PHPを使用して、見出しから目次を自動生成する事を目指します。
目次が挿入される場所は一番最初の見出しタグの前とします。
<div id="content">
<h2>見出し1</h2>
<h3>小見出し1</h3>
<h3>小見出し2</h3>
<h4>小小見出し1</h4>
<h5>小小小見出し1</h5>
<h3>小見出し3</h3>
<h2>見出し2</h2>
<h3>小見出し1</h3>
</div>
PHPで目次を自動生成したい場合はコンテンツを別ファイルに記述しておく必要があります。
ここではcontent.phpというファイル名にしております。
目次を自動生成するPHP
見出しから目次を自動生成するPHPは下記になります。
目次から見出しへ飛べるようにアンカーリンクも付けてくれます。
$content = file_get_contents('./content.php'); // コンテンツを取得
$content = autoTableOfContents($content); // 目次を自動生成
echo $content; // コンテンツを出力
function autoTableOfContents($content) {
$target = ['h2','h3','h4','h5'];
$pattern = '/<('.implode('|', $target).')([^>]*)>(.*?)<\/h\d>/';
if(preg_match_all($pattern, $content, $matches, PREG_SET_ORDER)){
$toc = '<div id="toc"><p>目次</p><ul>';
foreach($matches as $i => $match){
$id = "toc-$i"; // アンカーリンク用のID
list($h_tag, $h_name, $h_attr, $h_text) = $match; // 見出しタグ、見出しのタグ名、 見出しの属性、見出しのテキストを取得
$new_tag = "<$h_name id='$id' $h_attr>$h_text</$h_name>"; // idを付与した見出しタグを生成
$content = preg_replace("{".$h_tag."}", $new_tag, $content, 1); // idを付与した見出しタグに差替
$toc .= "<li class='toc-$h_name'><a href='#$id'>$h_text</a></li>"; // 目次リストを追加
}
$toc .='</ul></div>';
$content = preg_replace("/(<$target[0])/", "$toc$1", $content, 1); // 目次を一番最初の見出しタグの前に挿入
}
return $content;
}
WordPressで目次を自動生成したい場合
WordPressの場合は、先ほどのautoTableOfContents関数をfunctions.phpに記述して、コンテンツの出力箇所でフィルターフックを使用して以下のように記述したらOKです。
add_filter('the_content', 'autoTableOfContents');
the_content();
見た目の階層をわかりやすく
あとは見た目をよしなに整えるだけです。CSSのサンプルを載せておきます。
PHPが目次のリスト要素にtoc-H3などのクラスを付けてくれてるので階層をわかりやすくできます。
#toc .toc-H3 { margin-left: 15px }
#toc .toc-H4 { margin-left: 30px }
#toc .toc-H5 { margin-left: 45px }
#toc .toc-H6 { margin-left: 60px }
#toc {
border: 3px #BDBDBD solid;
padding: 30px;
margin: 50px 0;
}
#toc p {
font-weight: bold;
font-size: 24px;
margin-bottom: 10px;
}
#toc a{
font-size: 16px;
color: inherit;
}
#toc ul {
padding-left: 20px;
}
#toc li {
line-height: 1.8;
}
h2だけ目次にする
先ほどはh2からh5までを目次にしました。
どの見出しレベルまで目次にするかは、PHPの下記の部分で定義していますのでよしなに変更してください。
$target = ['h2','h3','h4','h5'];
以上、PHPで見出しから目次を自動生成する方法でした!