wordpress
WordPressでタグテンプレート使用で同タグ一覧+目次を付ける
最終更新日: 2025年3月8日
要件は連載ものが混在する書き物で、タグ付けで集めた投稿を書籍ライクに古い順から習べ、目次を自動生成するコード。
ほぼ使わない、忘れる、故に備忘。
<?php $tag = get_queried_object(); $tag_id = $tag->term_id; ?>
<?php if ($tag_id == 2): ?><?php /* 指定タグを持つ記事に目次を付け古い順にソートするタグid指定で条件分岐 */?>
<?php
$tag = get_queried_object(); // 現在のタグ情報を取得
// タグアーカイブページの場合のみ処理
if ($tag instanceof WP_Term) {
$args = array(
'tag_id' => $tag->term_id, // 現在のタグID
'orderby' => 'date',
'order' => 'ASC', // 古い順にする
'posts_per_page' => -1, // すべて取得
);
$tagged_posts = get_posts($args);
if ($tagged_posts) {
echo '<nav class="toc"><h2>目次</h2><ul>';
// **目次を生成**
$count = 1; // 連番用カウンター(ページ全体で一意にする)
foreach ($tagged_posts as $post) {
setup_postdata($post);
$content = apply_filters('the_content', $post->post_content);
if (preg_match_all('/<h3>(.*?)<\/h3>/', $content, $matches)) {
foreach ($matches[1] as $heading) {
$anchor = 'toc-' . $count; // 連番のIDを付与
echo '<li><a href="#' . $anchor . '">' . esc_html($heading) . '</a></li>';
$count++;
}
}
}
echo '</ul></nav>';
wp_reset_postdata(); // 投稿データのリセット
// **記事を出力**
$count = 1; // 連番用カウンターをリセット
foreach ($tagged_posts as $post) {
setup_postdata($post);
$content = apply_filters('the_content', $post->post_content);
// <h3> タグに ID を付与
$modified_content = preg_replace_callback('/<h3>(.*?)<\/h3>/', function($matches) use (&$count) {
$anchor = 'toc-' . $count;
$count++;
return '<h3 id="' . $anchor . '">' . $matches[1] . '</h3>';
}, $content);
echo '<article>' . $modified_content . '</article>';
}
wp_reset_postdata();
}
}
?>
<?php else:?>
その他のタグの場合の処理
<?php endif;?>
色々あるからね、後々なんか役に立つこともあるかもね。
修正版
各投稿が複数タグを持つ場合に該当投稿すべてが表示されない不具合があったので、投稿・タグが1・1でなくても済むように修正した。
※タグの条件分岐部は除いた。
<?php
$tag = get_queried_object();
if ($tag instanceof WP_Term) {
?>
<h2>
<?php
$str = $_SERVER['REQUEST_URI'];
$dec = urldecode($str);
$rep = preg_replace('/\/tag\/|\/page\/\d*/', '', $dec);
echo esc_html(str_replace('-', ' ', $rep));
?>
</h2>
<?php
$args = array(
'tag_id' => $tag->term_id,
'orderby' => 'date',
'order' => 'ASC',
'posts_per_page'=> -1,
'post_status' => 'publish',
);
$tagged_posts = get_posts($args);
if ($tagged_posts) {
$post_counter = 1;
$first_post = array_shift($tagged_posts);
setup_postdata($first_post);
?>
<article id="post-1" class="nbSct">
<h3>
<?php
echo esc_html(get_the_title($first_post->ID));
$ctm = get_post_meta($first_post->ID, 'subtitle', true);
?><?php if(empty($ctm)):?><?php else:?><span class="subtitle"><?php echo wp_kses_post(get_field('subtitle', $first_post->ID)); ?></span><?php endif;?>
</h3>
<?php echo apply_filters('the_content', $first_post->post_content); ?>
</article>
<?php
wp_reset_postdata();
echo '<nav class="hBox"><ul>';
echo '<li><a href="#post-1">' . esc_html(get_the_title($first_post->ID)) . '</a></li>';
$post_counter = 2;
foreach ($tagged_posts as $post) {
echo '<li><a href="#post-' . $post_counter . '">' . esc_html(get_the_title($post->ID)) . '</a></li>';
$post_counter++;
}
echo '</ul></nav>';
$post_counter = 2;
foreach ($tagged_posts as $post) {
setup_postdata($post);
?>
<article id="post-<?php echo $post_counter; ?>" class="nbSct">
<h3>
<?php
echo esc_html(get_the_title($post->ID)); // $first_post->ID から $post->ID に修正
$ctm = get_post_meta($post->ID, 'subtitle', true);
?>
<?php if(empty($ctm)):?><?php else:?><span class="subtitle"><?php echo wp_kses_post(get_field('subtitle', $post->ID)); ?></span><?php endif;?>
</h3>
<?php echo apply_filters('the_content', $post->post_content); ?>
</article>
<?php
$post_counter++;
}
wp_reset_postdata();
} else {
?>
<p>投稿が見つかりません。</p>
<?php
}
}
?>
<?php wp_reset_postdata(); ?>