WordPressテーマを自作する時に使うfunctions.phpコードまとめ

こんにちわ~おぐらです!
WorPressカスタマイズシリーズが一段落したので、今度は自作に関しての記事を書いています。

今回はWordPressのテーマにとって重要な役割を持つfunctions.phpについて、必ずと言っていいほど使うコードをピックアップしてお話します。
前半では最低限押さえておきたいことを、後半では実務でも使っているようなテクニックを紹介します。

なにか別のテーマを再利用する場合など自作以外でも使える内容ですので、カスタマイズ中にfunctions.phpで苦戦している方もぜひ活用してください。
少しでもテーマ作成の助けになれば幸いです。

目次

WordPressテーマを自作する時に使うfunctions.phpコードまとめ

まずはテーマを自作する時に最低限覚えておきたいものを4つお話します。
実際にこれがすべてではありませんが、すべては現実的じゃないので、とくに重要と思えるものだけに選別しました。

機能の有効化

1からテーマをつくると気づくことなんですが、functions.phpのない状態で記事投稿ページを見るとアイキャッチ画像を設定するところがありません。
実は、アイキャッチ画像を含め有効化されてはじめて使える機能があるということです。

特定のテーマ機能を有効化するには、add_theme_support関数を使います。
この関数はafter_setup_themeアクションにフックして、テーマを読み込んだ後実行されるようにするのが一般的です。

add_action( 'after_setup_theme', 'themeSetup' );
function themeSetup() {
    // アイキャッチ画像を使用する
    add_theme_support( 'post-thumbnails' );
    // wp_head内でtitleタグを出力する
    add_theme_support( 'title-tag' );
    // 投稿フォーマットを有効化する
    add_theme_support( 'post-formats', ['aside', 'gallery'] );
    // カスタム背景を使用する
    add_theme_support( 'custom-background' );
    // カスタムヘッダーを使用する
    add_theme_support( 'custom-header' );
    // フィードリンクを有効化する
    add_theme_support( 'automatic-feed-links' );
    // HTML5によるマークアップを許可
    add_theme_support( 'html5', ['search-form', 'gallery'] );
    // メニューを使用する
    add_theme_support( 'menus' );
    // ウィジェットを使用する
    add_theme_support( 'widgets' );
    // エディターのスタイルをカスタマイズ
    add_theme_support( 'editor-style' );
}

関数リファレンス/add theme support

CSSとJavaScriptの読み込み

カスタマイズ記事で何度も紹介してきましたCSSの読み込みに加えてJavaScriptの読み込みもお話しします
ページトップにスクロールする機能などをつけようとするとJavaScriptは必要になりますのでどちらも押さえておきましょう。

まずCSSを追加するにはwp_enqueue_style関数を使います。
最小構成ではハンドルネームとCSSファイルへのパスを渡すだけでオッケーです。

wp_enqueue_style( 'mytheme-style', get_file_theme_uri( 'style.css' ) );

読み込む順序を指定したい時は依存関係にあるCSSファイルのハンドルネームを配列で指定します。
配列なので複数の依存関係を指定できますよ。

wp_enqueue_style( 'mytheme-style-main', get_file_theme_uri( 'main.css' ) );
wp_enqueue_style( 'mytheme-style-sub', get_file_theme_uri( 'sub.css' ), ['main'] );

次にJavaScriptを読み込むにはwp_enqueus_script関数を使います。
仕組みはCSSとほとんど同じなので理解しやすいと思います。

wp_enqueue_script( 'mytheme-script', get_file_theme_uri( 'main.js' ) );

CSSと異なるのはJavaScriptをbodyタグの最後に読み込むように設定できる点です。
wp_enqueue_script関数の第5引数をtrueを渡すことでbodyタグの最後に読み込みます。

wp_enqueue_script( 'mytheme-script', get_file_theme_uri( 'main.js' ), [], '1.0.0', true );

第3引数は依存関係の指定、第4引数はファイルのバージョンを文字列で設定できます。
ここでasyncやdefer属性を付けたいけどできるの?と思ったら実にするどいです。

実は、wp_enqueue_script関数はasyncやdefer属性の付与をサポートしません。
実現するには①ハードコーディングする、②フィルターフックを利用するのどちらかになるのですが、過去に別の記事で解説しているため今回説明は省略します。

話を戻しまして、最後はwp_enqueue_scriptsアクションにフックしてCSSとJavaScriptを読み込むようにします。
関数名(loadMythemeScripts)やハンドルネームは任意で設定していただいて問題ありません。

add_action( 'wp_enqueue_scripts', 'loadMythemeScripts' );
function loadMythemeScripts() {
    // CSSを登録
    wp_enqueue_style( 'mytheme-style', get_file_theme_uri( 'style.css' ) );
    // JavaScriptを登録
    wp_enqueue_script( 'mytheme-script', get_file_theme_uri( 'main.js' ), [], '1.0.0', true );
}

関数リファレンス/wp enqueue script
関数リファレンス/wp enqueue style

カスタムメニューの定義

カスタムメニューの有効化、登録はregister_nav_menus関数またはregister_nav_menu関数を使用します。
複数か単数かの違いだけなので用途に応じて使い分けましょう。

add_action( 'after_setup_theme', 'initMenus' );
function initMenus() {
    register_nav_menus([
        'global_nav' => 'グローバルナビゲーション',
        'footer_nav' => 'フッターナビゲーション',
    ]);
}

配列のキーにはメニューの位置の識別子、値は管理画面での説明に使われます。
テンプレートファイルから呼び出す時に識別子を使います。

wp_nav_menu( ['menu' => 'global_nav'] );

関数リファレンス/register nav menus
関数リファレンス/register nav menu

サイドバーの作成

サイドバーをつくるにはregister_sidebar関数を使います。
サイドバーをつくっておくことで、任意の位置にウィジェットを出力できます。

register_sidebarにはサイドバーの名前や説明、HTMLの構造などの設定を渡すことができます。
サイドバーという名前ですが、必ずしも2カラムデザインでしか使えないというわけではありません。

add_action( 'widgets_init', 'initMainSidebar' );
function initMainSidebar() {
    register_sidebar([
        // 管理画面に表示する名前
        'name' => 'メインサイドバー',
        // サイドバーのID
        'id' => 'main_sidebar',
        // 管理画面に表示する説明
        'description' => 'メインサイドバーです',
        // 管理画面用のクラス
        'class' => '',
        // ウィジェットをラップするDOM(開始タグ)
        'before_widget' => '',
        // ウィジェットをラップするDOM(終了タグ)
        'after_widget' => '',
        // ウィジェットタイトルをラップするDOM(開始タグ)
        'before_title' => '',
        // ウィジェットタイトルをラップするDOM(終了タグ)
        'after_title' => '',
    ]);
}

テンプレートファイルからはidで呼び出すことができます。

dynamic_sidebar( 'main_sidebar' );

ウィジェット自体の作り方も紹介したかったのですが、記事の規模が大きくなりすぎるため別の機会といたします。

関数リファレンス/register sidebar

実務でも使えるfunctions.phpのテクニック

前半では最低限押さえておきたいものをお話しました。
ここからはもうちょっと進んで実務でも使うものをピックアップしてお話しします。

個人レベルでは使わないような内容かも知れませんが、こんなこともできるのか程度で見いていただければと思います。

カスタム投稿の作成

プラグインで実現されることが多いかと思いますが、functions.phpにコードを書く方法でもカスタム投稿をつくれます。
新しく投稿タイプをつくるという意味でWordPressにはじめからある投稿も投稿タイプのひとつですよ。

カスタム投稿をつくるために使うのはregister_post_type関数。
register_post_type関数には名前と、配列で詳細設定を渡します。

register_post_type($post_type, $args);

イベントというカスタム投稿をつくってみましょう。
カスタム投稿の作成はinitアクションにフックします。

add_action( 'init', 'initEventPostType' );
function initEventPostType() {
    $args = [
        'public' => true,
        'label' => 'イベント'
    ];
    register_post_type( 'event', $args );
}

上記はシンプルな設定ですが$args変数の内容を増やすことで細かく設定できます。
たとえばページごとに表示名を変えたり、管理画面のメニューの何番目に表示するなどの設定も可能なんです。

関数リファレンス/register post type

カスタムタクソノミーの作成

カスタム投稿と同様プラグインを使うことが多い印象ですが、こちらもプラグインなしでもつくれちゃいます。
タクソノミーって名前がハードルを上げてる気がしますが、WorsPressに最初から用意されている「カテゴリー」や「タグ」も実はタクソノミーなんです。

カテゴリーやタグの機能と同じものをユーザーが独自に作成するのでカスタムタクソノミーと言います。
カスタムタクソノミーをつくるために使うのはregister_taxonomy関数です。

register_taxonomy( $taxonomy, $object_type, $args );

引数にはタクソノミーの名前と関連づける投稿タイプ、最後に詳細設定の配列を渡します。
関連づける投稿タイプは配列で複数設定することもできますよ。

カスタムタクソノミーの場合もinitアクションを使います。
さきほどつくったイベント投稿タイプに関連づけるジャンルタクソノミーを作ってみましょう。

add_action( 'init', 'initGenreTaxonomy' );
function initGenreTaxonomy() {
    $args = [
        'label' => 'ジャンル',
        'hierarchical' => false,
    ];
    register_taxonomy( 'genre', 'event', $args );
}

上記は最低限の設定となり、$argsにキーバリューペアを増やすことでもっと細かく設定できます。
ポイントはhierarchicalキーで、値をtrueにするとカテゴリーの用に親子の階層を持ち、falseにするとタグと同様階層を持ちません。

関数リファレンス/register taxonomy

メインクエリを制御する

たとえば次の要望があったらあなたはどうしますか?

  • 投稿の一覧ページでは10件表示
  • イベント投稿タイプの一覧ページは20件表示
  • 検索結果ページは30件表示

メインループはメインクエリを発行してデータを取得して表示しています。
メインクエリを先述したような条件に応じて書き換えてあげることで、メインループの表示(今回は表示件数)を変更するということです。

ここで役に立つのがpre_get_postsアクションです。
クエリ実行前に呼ばれるアクションなので、ここにクエリを書き換える関数をフックしましょう。

add_action( 'pre_get_posts', 'your_function_name' );

フックする関数には変数$queryとしてクエリのオブジェクトが参照として渡されます。
参照なので関数内でglobal宣言したり、returnで返却する必要ありません。

便利な機能ですが使うにあたり注意点もあります。
まずはメインクエリに対して使うので、is_main_query関数でメインクエリかどうかを判定します。

さらに管理画面にも影響のあるアクションのため、is_admin関数で管理画面かどうかを判定し、管理画面の場合は使用しない処理にしましょう。

他にも、処理タイミングの関係で使えない条件分岐があります。
たとえばis_front_page関数は使えませんが、is_home関数は使えるなどです。

add_action( 'pre_get_posts', 'changeEventPostsPerPage' );
function changeEventPostsPerPage( $query ) {
    // 管理画面またはメインクエリでなければ処理を終了
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }

    /**
     * イベント投稿タイプの一覧ページなら
     * 表示件数を20件にする
     */
    if ( is_post_type_archive( 'event' ) ) {
        $query->set( 'posts_per_page', 20 );
    }
}

冒頭のイベント投稿タイプの表示件数を20件にする処理です。
クエリオブジェクトの持つsetメソッドで変更するクエリと変更する値を変更しています。

実際に使う時はクエリの種類や値を適宜変更してください。
pre_get_postsを覚えれば、メインクエリを自由自在に使いこなせるようになりますよ。

pre_get_posts

リライトルールを追加する

WordPressはもともと定義されているリライトルールをもとにパーマリンクを設定しますが、要望によってはどうしても実現できない場合もあります。
そこで独自にリライトルールを追加するわけですね。

たとえばデフォルトだとイベント投稿タイプの年別一覧ページのURLは次のようになります。

https://hogehoe.com/2020/?post_type=event

パラメーターだとなんだかわかりにくいですね。
リライトルールを追加して次のように変更してみましょう。

https://hogehoe.com/event/2020/

リライトルールを追加するにはadd_rewrite_rule関数を使います。
第1引数にリライトルール(表示したいURL)を正規表現で設定します、第2引数はリライトルールの正規表現がマッチした時に呼び出すURLを指定します。

add_action( 'init', 'rewriteEventYearArchive' );
function rewriteEventYearArchive() {
    add_rewrite_rule('([^/]+)/([0-9]{4})/?$', 'index.php?post_type=$matches[1]&year=$matches[2]', 'top');
}

第1引数の括弧で囲った部分が第2引数の$matches変数に代入されます。
例の場合、([^/]+)のところに投稿タイプの名前が入り、([0-9]{4})には年が入ります。

/event/2020/というリクエストがきた場合、実際に呼び出しているURLは次のようになります。

index.php?post_type=event&year=2020

functions.phpからリライトルールを追加した場合は確実に管理画面のパーマリンク設定から1度変更を保存してください。
管理画面からなにも設定を変更しなくてもいいのでとにかく変更を保存してください。

なぜかというとパーマリンクを更新しないとリライトルールの追加が反映されないからです。
動作を確認して反映されないときはパーマリンクを更新してみてください。

ちなみにリライトルールに関するチュートリアルや例でflush_rewrite_rules関数をinitアクションにフックして使っているものがありますが、マネはやめましょう。
initアクションにフックすることは負荷が高いため、公式でもバッドプラクティスと明言されています。

リライトルールの追加、変更後は、flush_rewrite_rules関数をフックする方法ではなく、管理画面からパーマリンクを更新しましょう。

Rewrite API/add rewrite rule

functions.phpにはPHPのスキルが重要

functions.phpに書くことはテンプレートファイルと比較するとほとんどPHPになるので、PHPの構文とWordPressの仕組みを理解しておく必要があります。
このためfunctions.phpについて学習を進めるのであれば、PHPの比率を上げつつ、WordPressについて学ぶことのできるものがいいかなと思います。

書籍であればWordPressジャンルの中でもPHP中心のものを選んだほうが学習しやすいでしょう。
たとえば「WordPressユーザーのためのPHP入門 はじめから、ていねいに。」はLesson7ではメインクエリ、サブクエリ、Lesson10ではfunctions.phpに記述するコードという内容なのでfunctions.phpについてこれから学びたい方にはマッチしていると思います。

前の記事
経験者の考えるWordPressテーマ自作のメリット3つ【副業に活かそう】
次の記事
【入門】WordPress自作テーマのベースをつくろう【初心者向け】