こんにちは、山本です。

さて、過去2度に渡りWordPressのプラグイン作成初級編の説明をさせて頂きました。

主に、プラグインを作成するにあたり、必要な知識や、方法の説明ばかりだったかと思います。

ですので、今回よりはその応用編として、より実践的な実作業で必要とした機能や、不満に思い拡張して行ったものなどを説明していこうと思います。

今回の目的

  • ルーティングを拡張する。

さて、WordPressにてサイト構築を行うにあたり、アーカイブについて不満に感じることがあります。

それは、アーカイブでは年別、月別、日別といったことは可能なのですが、特定のカテゴリに所属する記事の年、月、日のアーカイブを表示することが出来ません。

これは、とても不便ですので今回はこれを拡張します。

フィルターを探す

早速、ルーティングを拡張するにはどの、フィルターを使用すればよいのかを調べます。

codexを確認すると、ルーティングをフック出来そうなフィルターが幾つか見つかりました。

p001

どれが良いのかと、それぞれの説明を読んでみると、タクソノミーやカスタム投稿タイプ毎にリライトルールを設定可能なフィルターがあるようですので、今回はこれを使用しましょう。

Filter: {$permastruct}_rewrite_rules
 - Can be used to create or modify rewrite rules for any custom permastructs, such as taxonomies or custom post types.

作成

  • スケルトン
    いつものように、スケルトンを作成します。
// wp-content/plugins/routingPlugin/routingPlugin.php
/*
Plugin Name: routingPlugin
Plugin URI: http://www.adjust.ne.jp
Description: テンプレート振り分けプラグイン
Author: ADjust Co.,Ltd.
Author URI: http://www.adjust.ne.jp
Version: 1.0
*/
  • フィルター設置
    カテゴリーを対象とするフィルターを設置します。
    add_filter('category_rewrite_rules', 'addDateRewriteRules');
    add_filter('init', 'rewriteFlush');

    function rewriteFlush()
    {
      global $wp_rewrite;
      $wp_rewrite->flush_rules();
    }

    function addDateRewriteRules($rewrite_rules)
    {
      var_dump($rewrite_rules);
    }

「$wp_rewrite->flush_rules();」の記述がありますが、これは後述します。

  • 値の確認
    さて、フィルターを通過している値ですが、どのようなものか「$rewrite_rules」を確認します。
    array (size=4)
      'category/(.+?)/feed/(feed|rdf|rss|rss2|atom)/?$' => string 'index.php?category_name=$matches[1]&feed=$matches[2]' (length=52)
      'category/(.+?)/(feed|rdf|rss|rss2|atom)/?$' => string 'index.php?category_name=$matches[1]&feed=$matches[2]' (length=52)
      'category/(.+?)/page/?([0-9]{1,})/?$' => string 'index.php?category_name=$matches[1]&paged=$matches[2]' (length=53)
      'category/(.+?)/?$' => string 'index.php?category_name=$matches[1]' (length=35)

4種類のルールがありました。

左のキー名が、ルーティングのルールになります。
そして、右の値がパラメータの設定となっており、キー名でグルーピングした値を、「category_name」「paged」などのパラメータに設定しています。

まず上の2つですがfeedとありますのでこれはrssを表示するルールになります。
次にpageとありますが、これはページネーション用のルールになります。

最後にpageもfeedもついていないルールがありますが、これが通常のカテゴリー用ルールになります。
これの末尾に日付を付けられるように拡張します。

  • ルーティングルールの追加
    function addDateRewriteRules($rewrite_rules)
    {
      $newRule = array();

      foreach($rewrite_rules as $key => $value)
      {
        if (!preg_match('/page/', $value) && !preg_match('/feed/', $value))
        {
          $str = preg_replace('/\?\$/', '', $key);

          //年別
          $newRule[$str.'date/([0-9]{4})/?$'] = $value.'&year=$matches[2]';
          $newRule[$str.'date/([0-9]{4})/page/?([0-9]{1,})/?$'] = $value.'&year=$matches[2]&paged=$matches[3]';
          //月別
          $newRule[$str.'date/([0-9]{4})/([0-9]{2})/?$'] = $value.'&year=$matches[2]&monthnum=$matches[3]';
          $newRule[$str.'date/([0-9]{4})/([0-9]{2})/page/?([0-9]{1,})/?$'] = $value.'&year=$matches[2]&monthnum=$matches[3]&paged=$matches[4]';
          //日別
          $newRule[$str.'date/([0-9]{4})/([0-9]{2})/([0-9]{1,2})/?$'] = $value.'&year=$matches[2]&monthnum=$matches[3]&day=$matches[4]';
          $newRule[$str.'date/([0-9]{4})/([0-9]{2})/([0-9]{1,2})/page/?([0-9]{1,})/?$'] = $value.'&year=$matches[2]&monthnum=$matches[3]&day=$matches[4]&paged=$matches[5]';
        }
      }

      return $newRule + $rewrite_rules;
    }

これにより、以下のURLで年別、月別、日別のカテゴリーアーカイブページが出来ました。
※ 固定の文字列で「date」と付与しているのは、それがない場合日付なのかpost_idなのかが判別出来ないためです。

    /category/%category%/date/%year%/
    /category/%category%/date/%year%/%month%/
    /category/%category%/date/%year%/%month%/%day%/
  • 確認用サンプル
    以下のように、2つのカテゴリにそれぞれ4つの記事を作成しました。
    それぞれの記事には異なる公開日を設定しています。
    カテゴリ名:category1
      記事公開日:2014-09-01
      記事公開日:2015-09-01
      記事公開日:2015-08-01
      記事公開日:2015-09-03
    カテゴリ名:category1
      記事公開日:2014-09-01
      記事公開日:2015-09-01
      記事公開日:2015-08-01
      記事公開日:2015-09-03

確認

category1の2015年アーカイブを確認します。

p002

2015年の絞り込みが出来ました。

次に、2015-09と2015-09-03の絞り込みを試します。

p003

p004

月別も、日別の正常に動作しています。

補足

  • パラメータ

今回はカテゴリーのアーカイブですので、「category_name, year, monthnum, day」のパラメータを使用しました。

ですが、WordPressには他にもパラメータが存在ます。

WordPressのURLはルーティングのルールと、それに設定するパラメータで表示する画面が決まりますので、codexの情報を元にすれば、任意のURLを自由に作成することが出来ます。

WordPress Query Vars – WordPress Codex 日本語版

  • flush_rules

さて、プラグインで「flush_rules」を行っていますがこれが何かという説明です。

ます、ルーティングですがこれは表示の度に生成しているものではなく、「wp_options」テーブルの「rewrite_rules」に予め用意されています。

これは、ルーティングの生成が非常に重い動作である為です。

「category_rewrite_rules」はルーティングの生成時に動作するフィルタですので、ルーティングの再生成を行う必要があります。

その為「flush_rules」を行っています。

尚、ルーティングの再生成ですがこれは毎回実行する必要があるものではなく、ルーティングの変更を行った時のみ実行すればよいものです。
つまりは、プラグインの有効化、無効化の際に行うだけで十分であるかと思います。

まとめ

今回はカテゴリ用のルーティングを元に説明をさせて頂きました。
ですが、これは別にカテゴリのURL拡張のみに留まるものではありません。

基本的に、WordPressのURLは管理画面よりパーマリンク設定にて行いますが、それには沿わない特殊なURLが必要となることもあったりします。

今回のようにフィルターを通過時に、値を加工することにより、特殊なURLが必要なケースにも対応が出来るのではと思います。

さて、次回ですがテンプレートの振り分けを説明する予定しています。

今回作成したプラグイン:routingPlugin