WordPress のカスタムフィールドを使って記事に自動でシリアル番号を振る

WordPress のカスタムフィールドを使って記事に自動でシリアル番号を振る

メリークリスマス。今年のベスト映画は『キカイダーREBOOT』…と半年くらい思っていましたがここにきて『ベイマックス』にやられてしまっている kagata です。

WordPress で記事を一覧表示する際に、その記事が全体の何番目かを示す番号を振ってほしいという要望を受けることがたまにあります。細かい要件によっていろいろ考えられる実装方法のうち、ここではカスタムフィールドに番号を保持するアイディアをご紹介します。

カスタムフィールドというと管理画面に入力欄があるものを想像しがちですが、今回は入力欄を作らず記事投稿時に自動でデータを登録するようにしています。シリアル番号以外にも、アイディアしだいでいろんな使い方ができそうです。

シリアル番号の要件

今回実装するシリアル番号はおおよそこんな感じのものです:

  • ある投稿タイプの記事に、新規投稿された順に1から番号を振っていく
  • 途中で記事を削除したら、その記事の持っていた番号は欠番になる。間を詰めることはしない
  • 手動での番号の振り直しや並び替えには対応しない

わりとシンプルに。

シリアル番号を実装する PHP コード

いきなりコードを一式のせてしまいます。どーん。

/*
 * 特定の投稿タイプにシリアル番号を振るためのクラス
 */
class NumberField {
    protected $_postType; // 採番対象の投稿タイプ名

    public function __construct( $post_type = 'post' ) {
        $this->_postType = $post_type;
        add_action( 'save_post_' . $this->_postType, array( $this, 'setNumber' ) );
    }

    /*
     * 番号を格納するカスタムフィールドのキーを返す
     */
    protected function _getMetaKey() {
        return 'number_field_' . $this->_postType;
    }

    /*
     * 採番用シーケンスを格納するサイトオプションのキーを返す
     */
    protected function _getSequenceKey() {
        return 'number_sequence_' . $this->_postType;
    }

    /*
     * 当該投稿タイプが投稿されたら番号を付与する
     */
    public function setNumber( $post_ID ) {
        // 採番済みならば何もしない
        if ( $this->getNumber() !== '' )
            return;

        // 採番用シーケンスが既存の場合は1進める。ない場合は1から始める。
        $sequence = get_option( $this->_getSequenceKey() );
        $sequence = ( !empty( $sequence ) ) ? $sequence + 1 : 1;

        // カスタムフィールドに番号を追加する
        if ( update_post_meta( $post_ID, $this->_getMetaKey(), $sequence ) ) {
            // カスタムフィールドの更新に成功したら、シーケンスをオプションに格納する
            update_option( $this->_getSequenceKey(), $sequence );
        }
    }

    /*
     * 引数で指定された投稿 ID の持つ番号を取得する
     */
    public function getNumber( $post_ID = null ) {
        // 引数がなければ現在の投稿 ID を使う
        if ( empty( $post_ID ) ) {
            $post_ID = get_the_ID();
        }
        return get_post_meta( $post_ID, $this->_getMetaKey(), true );
    }
}
$numberField = new NumberField( 'cpt' ); // 採番対象の投稿タイプ名を指定する
$postNumberField = new NumberField();    // デフォルトでは投稿タイプ「投稿」に番号を振る

まずはこれをテーマの functions.php に書きます。そして、各テンプレートで番号を表示するには下のようにします。

<h1>エントリーナンバー<?php echo $numberField->getNumber(); ?></h1>

これで、投稿順に番号が振られ、画面に表示することができます。

コードの解説

それでは、上のコードを順に見ていきましょう。

記事の投稿処理に独自の処理をはさむ

NumberField::__construct() で、記事の投稿処理に独自の処理をはさむ記述をしています。今回の場合は、カスタムフィールドにシリアル番号を格納する処理ですね。

add_action( 'save_post_' . $this->_postType, array( $this, 'setNumber' ) );

投稿処理中に通過するいくつかのアクションフックのうち、今回は save_post_[投稿タイプ名] を使うことにしました。アクションフック save_post は投稿タイプにかかわらず通過するのに対して、こちらは特定の投稿タイプの記事を投稿するときだけ通過します。条件分岐を自分で書く手間が省けて、便利ですね。

記事のシリアル番号をカスタムフィールドに格納する

NumberField::setNumber() で、カスタムフィールドにシリアル番号を格納します。本質的なのはこの部分。

// カスタムフィールドに番号を追加する
if ( update_post_meta( $post_ID, $this->_getMetaKey(), $sequence ) ) {
    // カスタムフィールドの更新に成功したら、シーケンスをオプションに格納する
    update_option( $this->_getSequenceKey(), $sequence );
}

WordPress の関数 update_post_meta() でカスタムフィールドにデータを格納します。カスタムフィールドの更新に成功したら true が返ってくるので、これを受けて関数 update_option() で WordPress のサイトオプションに今登録した番号を記録しておきます。

そして、次回の記事投稿の際には、このサイトオプションを関数 get_option() で呼び出します。

$sequence = get_option( $this->_getSequenceKey() );

次の記事には、呼び出した番号に1加えた値をカスタムフィールドに格納してやればよいわけですね。

カスタムフィールドからシリアル番号を読み出す

カスタムフィールドの読み出しには関数 get_post_meta() を使います。

return get_post_meta( $post_ID, $this->_getMetaKey(), true );

今後の展望

  • 削除された記事の番号を欠番にせず間を詰めるにはどうしたらいいでしょう。記事削除のアクションフックで、残りの記事に番号を振り直す処理をはさむとか?
  • 番号を手動で振り直すこともできるようにするには?管理画面の投稿フォームにカスタムフィールドの入力欄を設置すればよさそう。プレースホルダにデフォルトのシリアル番号を表示したうえで、手動入力もできるようにしておけば柔軟かも。
  • 複数の投稿タイプで採番をするなら、投稿タイプ名を配列で持たせて一つのオブジェクトでまかなえるようにしたほうが便利そう。
  • いっそ管理画面もつけてプラグイン化するとか。

まとめ

  • 記事投稿に独自の処理を追加するなら、アクションフック save_postsave_post_[投稿タイプ名] が使える
  • カスタムフィールドを更新するには update_post_meta() 、カスタムフィールドを読み出すには get_post_meta() を使う
  • サイトオプションを更新するには update_option() 、サイトオプションを読み出すには get_option() を使う

参考

記事投稿に関連するアクションフックはほかにもいくつかあります。次の記事がくわしいです。

  • このエントリーをはてなブックマークに追加

この記事を読んだ人にオススメ