月別アーカイブリストをコンパクトにする方法

February 4, 2011 – 5:27 pm

ブログの運営を、それなりの期間、継続しているとサイドバーに表示されている「月別アーカイブリスト」の行数が多くなってしまう。こうなると、サイドバーのスペースが「アーカイブリスト」で占有されてしてしまい、かなりうっとうしくなってくる。
こうした事態を避けるため、「月別アーカイブリスト」をコンパクトに表示することにした。
方法はいたって簡単。サイドバーを表示しているPHPプログラムを修正し、アーカイブリストの出力をバッファリングして必要な情報を抽出、これを好きな形式に出力できるようにすればよい。
PHPプログラムのソースを含め、その一方法をメモしておいた。

WordPressの「月別アーカイブリスト」: このブログはWordPressを使って運営している。WordPressでは、アーカイブリストの出力にはwordpress特有のphp関数、wp_get_archives() が使われている。サイドバーへの月別のアーカイブリストを出力は以下のようになっている:

<li><h2>Archives</h2>
    <ul>
      <?php wp_get_archives('type=monthly'); ?>
    </ul>
</li>

ここでwp-get-archives()からの標準出力の形式は次のようなものである:

<li><a href='http://memorandum.yamasnet.com/archives/Post-date/2011/02' title='January 2011'>January 2011</a></li>
<li><a href='http://memorandum.yamasnet.com/archives/Post-date/2011/01' title='January 2011'>January 2011</a></li>
<li><a href='http://memorandum.yamasnet.com/archives/Post-date/2010/12' title='December 2010'>December 2010</a></li>

      (以下省略)

アーカイブリストの中身を抽出: 上記したwp-get-archives()そのままでは、カスタマイズすることができない。カスタマイズするために専用の関数を作成することも考えられるが、そう容易ではない。

最も簡単な方法は、wp-get-archives()の出力結果をバッファリングし、処理可能な形式にするのがよい、と考えられる。バッファリングするのに ob_get_contents()なんて便利なphp関数がある。これを用いればよい。

この関数の使用方法を説明するためにこれを用いた簡単なphpプログラムとそれを実行した場合の出力を以下に示す:

phpサンプルプログラム:
<?php
  ob_start();
     echo "Sample Output";
     $out = ob_get_contents();
  ob_end_clean();
  echo "Buffering End!" . "\n";
  var_dump($out);
?>

出力:
Buffering End!
string(13) "Sample Output"

このサンプルプログラムに見られるように、標準出力をバッファリングするには、まず、バッファリングの開始を宣言する ob_start()を実行する。これ以降、ob_end_clean()が実行されるまでの間、標準出力はバッファリングの対象とされる。バッファリングされたデータの取り出しはob_get_contents() により行なわれる。

この方法を用いて、wp_get_archives()からの標準出力をバッファリングしてみよう。

バッファリングした内容を変数 $buffer に格納するには次のようにすればよい:

    ob_start();
      wp_get_archives('type=monthly');
      $buffer = ob_get_contents();
    ob_end_clean();

ここで $buffer に格納したデータから必要な部分を抽出する。抽出には、正規表現によるマッチングを用いる(ここでは、関数 preg_match_all() を使った)。正規表現については、以前このブログで触れている(「Webページへの公開情報を自動的に抽出・取得する」)。

上述したwp_get_archive() の出力例をpreg_match_all()を用いて処理する例を以下に示す。

まず、サンプルのソースをしめす:

<?php
$buffer = "
<li><a href='http://memorandum.yamasnet.com/archives/Post-date/2011/02' title='January 2011'>January 
2011</a></li>
<li><a href='http://memorandum.yamasnet.com/archives/Post-date/2011/01' title='January 2011'>January 
2011</a></li>
<li><a href='http://memorandum.yamasnet.com/archives/Post-date/2010/12' title='December 2010'>Decembe
r 2010</a></li>
";
   preg_match_all("/<a href=.*Post-date\/([^>]+)\/([^>]+)\' title=.*\'>/", $buffer, $cell, PREG_PATTE
RN_ORDER);
print_r($cell);
?>

これを実行すると以下になる:

Array
(
    [0] => Array
        (
            [0] => <a href='http://memorandum.yamasnet.com/archives/Post-date/2011/02' title='January 2011'>
            [1] => <a href='http://memorandum.yamasnet.com/archives/Post-date/2011/01' title='January 2011'>
            [2] => <a href='http://memorandum.yamasnet.com/archives/Post-date/2010/12' title='December 2010'>
        )

    [1] => Array
        (
            [0] => 2011
            [1] => 2011
            [2] => 2010
        )

    [2] => Array
        (
            [0] => 02
            [1] => 01
            [2] => 12
        )

)

ここで理解されるように、「月別アーカイブ」の表示に必要なデータは配列cellに格納され、あとはこの配列内のデータを組み合わせて、好みの形にHTML化すればよい。

HTMLデータの作成: 以上述べた諸手続きをあわせてHTMLデータを作成し、これを冒頭部分に示したサイドバーの関連部分(<ul>から</ul>まで)と置き換えれば目的の「月別アーカイブ」となる。

今回作成したphpのソースを以下に示す:

<?php
    ob_start();
      wp_get_archives('type=monthly');
      $buffer = ob_get_contents();
    ob_end_clean();

    preg_match_all("/<a href=.*Post-date\/([^>]+)\/([^>]+)\' title=.*\'>/", $buffer, $cell, PREG_PATTERN_ORDER);
    $imax = count($cell);
    $jmax = count($cell[0]);
    $year = "init";
    $year_blank = "   ";
    $jmonth = 0;
    $mmax = 12;

    echo "<table id=\"archive\"> \n";
    for( $j=0; $j<$jmax; $j++) {
     if ( $jmonth == 6 ) {
                 echo "</tr> \n";
                 echo "<tr>\n<td>$year_blank</td> \n";
     } 
    if( strcmp($year,$cell[1][$j])!= 0 ) {
         if ( strcmp($year,"init") !=0) {
              for ( $m=$jmonth; $m<$mmax; $m++ ) { 
                  echo "<td> </td> \n";
                   if ( $m == 5 ) break;
              }
              echo "</tr>\n";
         }
         $year = $cell[1][$j];
         echo "<tr>\n<td>".$year."</td>\n<td>".$cell[0][$j].$cell[2][$j]."</a></td> \n";
         $jmonth = 1;
     }
     else {
         echo "<td>".$cell[0][$j].$cell[2][$j]."</a></td> \n";
         $jmonth = $jmonth + 1;
     }
     if ( $jmonth == 12 && $j==$jmax-1 ) {
         echo "</tr>\n";
     }
    }
    for ( $m=$jmonth; $m<$mmax; $m++ ) {
      echo "<td> </td> \n";
      if ( $m == 5 ) {
            echo "</tr>\n";
            break;
      }
    }
    echo "</table>\n";
?>

サイドバーの「月別アーカイブ(Archives)」にその結果が反映されている。かなりコンパクトな表示形式になることが理解されるはずだ。この部分の「月」表示部分をクリックすればアーカイブページが開かれるのを確認することができる。

まとめ: ここで述べた方法、「月別アーカイブリスト」のカスタマイズに限らず、いろいろな場面で使えるのではないかと思う。phpのプログラミングで工夫をすれば、もっと良い表示になると思う。

今回示した表示方法、あまり凝ったものではなくシンプルなものになっているが、機能的には十分ではないかと考える。

それでは、この辺で!


  1. 2 Trackback(s)

  2. Sep 14, 2012: [WP]月別アーカイブを年別に表示する方法 | MEKEKEMORA
  3. Nov 9, 2013: WordPressを3.7.1に更新したらブログに不具合発生 | Yama's Memorandum

Post a Comment