リンク付きの目次を自動生成する

このブログは見出し+本文のセットをリピーターフィールドで生成し、好きな数だけセクションを作れるようにしてあります。そして、各セクションへのページ内リンク付き目次を冒頭に自動生成するようにしてみました。このような形式のブログをよく見かけるので、ひょっとしたら専用のプラグインがあるのかもしれませんね。

実際は、以前の記事「Repeater Fieldを利用してマルチカラムレイアウトを実現」で解説したボックスが本文フィールドの中に内包されていて、リピーターフィールドが入れ子になっています。そして(英文でブログを書くつもりはほぼありませんが…)一応多言語対応もしているため、元のソースはもっと複雑です。わかりやすくするために目次を作る機能に限定して書き直してあります。

カスタムフィールドの設定

まず、見出し+本文のセット(=セクション)用のリピーターフィールドを作ります。

カスタムフィールドの設定画面で、ブログの投稿画面で使用するためのフィールドグループを新規追加します。続いてセクション用のフィールドを追加、そのフィールドタイプをRepeaterにします。

Fig1

するとサブフィールドが設定できるようになります。見出し用のフィールド(テキスト)と本文用のフィールド(テキストエリアかwysiwyg)を設定します。

Fig2

テーマファイルへの記述:セクション部分

リピーターフィールドsectionがある時、そのサブフィールドである見出し(c_title)と本文(c_txt)を出力します。

目次からセクションの先頭にリンクさせたいので、見出しにid属性を追加します。任意のid名に続いて連番が自動出力されるよう、ループの冒頭に初期値を設定し…

$k = 1;

ループの終わりに 

$k++;

 を追記します。1回ループするごとに増える数値をid属性値の一部として出力します。

id="sec0<?php echo $k;?>"
<?php if(have_rows('section')): while(have_rows('section')):the_row(); $k=1;?>

<h3 id="sec0<?php echo $k;?>"><?php the_sub_field('c_title');?></h3>
<?php the_sub_field('c_txt');?>

<?php $k++; endwhile; endif;?>

テーマファイルへの記述:目次部分

目次を出力するだけなら下記の記述を冒頭に追記すればOKです。出力する内容が異なるだけで、セクション出力部分と同じ構造ですね。

<?php if(have_rows('section')):?>

<ul>

 <?php $i=1; while(have_rows('section')): the_row();?>

 <li><a href="#sec0<?php echo $i;?>"><?php the_sub_field('c_title');?></a></li>

 <?php $i++; endwhile;?>

</ul>

<?php endif;?>

セクションの数が一つしかないときは目次は不要なので、条件分岐を追加します。

get_field_object()はフィールドの中身を配列として取得するAdvanced Custom Fields独自の関数です。

配列の中からvalue(カスタムフィールドに入力した値)を取り出し、count関数でその個数をカウントします。その数が1より大きいときのみ目次を出力するようにしました。

<?php if(have_rows('section')):?>

 <?php $field=get_field_object('section');
 $count=(count($field['value']));
 //sectionの数が2以上のとき目次を出力
 if($count>1):
 ?>

<ul>

 <?php $i=1; while(have_rows('section')): the_row();?>

 <li><a href="#sec0<?php echo $i;?>"><?php the_sub_field('c_title');?></a></li>

 <?php $i++; endwhile;?>

</ul>

 <?php endif;?>

<?php endif;?>

テーマファイルへの記述:全体

2つのソースを合わせる場合、  if(have_rows('section')) 部分が重複するのでまとめてしまいましょう。

<?php if(have_rows('section')):?>

  <?php $field=get_field_object('section');
    $count=(count($field['value']));
    //sectinの数が2以上のとき目次を出力
    if($count>1):
  ?>

  <ul>

    <?php $i=1; while(have_rows('section')): the_row();?>

    <li><a href="#sec0<?php echo $i;?>"><?php the_sub_field('c_title');?></a></li>

    <?php $i++; endwhile;?>

  </ul>

  <?php endif;?>

  <?php //セクション出力
  while(have_rows('section')): the_row(); $k=1;?>

  <h3 id="sec0<?php echo $k;?>"><?php the_sub_field('c_title');?></h3>

  <?php the_sub_field('c_txt');?>

  <?php $k++; endwhile;?>

<?php endif;?>