Uweb

【プラグイン不要】functions.phpで目次を追加する

こんにちは。やまぐちなな(@nana_winter_web )です。

JavaScriptで表示していた目次をPHPで表示するように変更したときのコードを少し改造したものを公開します。

コード

functions.php
/**
 * 目次.
 *
 * @param string $content 記事の内容.
 * @return string $content 目次追加後の内容.
 */
function add_index( $content ) {
	if ( is_single() ) {
		$pattern = '/<h[1-6]>(.+?)<\/h[1-6]>/s';
		preg_match_all( $pattern, $content, $elements, PREG_SET_ORDER );

		if ( count( $elements ) >= 1 ) {
			$toc          = '';
			$i            = 0;
			$currentlevel = 0;
			$id           = 'chapter-';

			foreach ( $elements as $element ) {
				$id           .= $i + 1;
				$regex         = '/' . preg_quote( $element[0], '/' ) . '/su';
				$replace_title = preg_replace( '/<(h[1-6])>(.+?)<\/(h[1-6])>/s', '<$1 id="' . $id . '">$2</$3>', $element[0], 1 );
				$content       = preg_replace( $regex, $replace_title, $content, 1 );

				if ( strpos( $element[0], '<h2' ) !== false ) {
					$level = 1;
				} elseif ( strpos( $element[0], '<h3' ) !== false ) {
					$level = 2;
				} elseif ( strpos( $element[0], '<h4' ) !== false ) {
					$level = 3;
				} elseif ( strpos( $element[0], '<h5' ) !== false ) {
					$level = 4;
				} elseif ( strpos( $element[0], '<h6' ) !== false ) {
					$level = 5;
				}

				while ( $currentlevel < $level ) {
					if ( 0 === $currentlevel ) {
						$toc .= '<ol class="index__list">';
					} else {
						$toc .= '<ol class="index__list_child">';
					}
					$currentlevel++;
				}

				while ( $currentlevel > $level ) {
					$toc .= '</li></ol>';
					$currentlevel--;
				}

				// 目次の項目で使用する要素を指定
				$toc .= '<li class="index__item"><a href="#' . $id . '" class="index__link">' . $element[1] . '</a>';
				$i++;
				$id = 'chapter-';
			} // foreach

			// 目次の最後の項目をどの要素から作成したかによりタグの閉じ方を変更
			while ( $currentlevel > 0 ) {
				$toc .= '</li></ol>';
				$currentlevel--;
			}

			$index = '<div class="single__index index" id="toc"><div class="index__title">目次<button class="index__button">閉じる</button></div>' . $toc . '</div>';
			$h2    = '/<h2.*?>/i';

			if ( preg_match( $h2, $content, $h2s ) ) {
				$content = preg_replace( $h2, $index . $h2s[0], $content, 1 );
			}
		}
	}
	return $content;
}
add_filter( 'the_content', 'add_index' );

上記のコードをfunctions.phpに追加すれば、1つ以上h2見出しがある記事は自動的に目次が表示されます。

出力される結果は、この記事の目次を見てもらうとわかりやすいですが、liの中にolが入る感じになっています。

classも付けているのでいい感じにスタイルを整えてください。

使用するときのポイント

どこでも書かれていることなので、すでにご存じかもしれませんが、functions.phpを編集するときはバックアップを取ってFTPでアップロードしてください。
functions.phpを更新してアップロードしたら画面が真っ白になったというのはよくあることです。

関数名がよくある単語過ぎて、他の関数と被ってくるかもしれないので、変更しないとエラーが出るかもしれません。

まとめ

目次をJavaScriptからPHPに変更したことで、JavaScriptがオフの環境でも目次が表示されるようになりました。

プラグインを使わないと、サイトが早く表示されたりと良いこともあるので、良ければ使ってみてください。

シェア

スポンサーリンク

最新記事