WordPress の functions.php とは|書き方の基本と、プラグインに書くべきものの見分け方

結論

WordPress の functions.php は、有効化しているテーマに機能を追加するための PHP ファイルです。Theme Handbook は「functions.php はプラグインのように振る舞い、サイトに機能を追加する」と説明しています。書き方の基本は次の3つです。

  1. 処理は関数にまとめ、add_action() / add_filter() で適切なフックに登録する(ファイルに直接処理を書き並べない)
  2. 関数名にはテーマ固有の接頭辞を付ける
  3. ファイル末尾の ?> は書かない

そして、テーマを変えても残すべき機能はプラグインに書く、というのが公式の推奨です。

原因・仕組み

functions.php とプラグインの違い

Handbook によると、両者の違いは次のとおりです。

項目 functions.php プラグイン
置き場所 テーマのフォルダ wp-content/plugins
ヘッダー 不要 専用のヘッダーが必要
効く範囲 有効なテーマのときだけ テーマに関係なく有効

同じ処理はどちらでも書けますが、Handbook は「サイトの見た目に関係なく使えるべき機能は、プラグインに入れるのがベストプラクティス」としています。

読み込まれるタイミング

functions.php はすべてのプラグインの読み込みが終わった後に読み込まれます(Handbook)。子テーマを使っている場合は、子テーマの functions.php が親テーマより先に読み込まれ、親を置き換えるのではなく両方が読み込まれます。読み込まれた直後に after_setup_theme が実行され、その後に init が来ます。

このため、functions.php の中でいきなり処理を実行すると、まだ準備ができていない機能に触れることがあります。フックに登録して、WordPress が呼び出すのを待つのが基本の形です。

手順(サンプルコード)

基本の書き方

<?php
// テーマ固有の接頭辞 wl1_ を付ける
if ( ! function_exists( 'wl1_site_label' ) ) {
    function wl1_site_label() {
        return 'WL1:' . get_bloginfo( 'name' );
    }
}

// テーマの機能宣言は after_setup_theme
add_action( 'after_setup_theme', function () {
    add_theme_support( 'post-thumbnails' );
} );

// 投稿タイプ・ショートコードなどの登録は init
add_action( 'init', function () {
    // register_post_type() や add_shortcode() をここで
} );

// 値を変えるときはフィルターで、必ず return する
add_filter( 'excerpt_length', function ( $length ) {
    return 40;
} );

function_exists() で囲むのは、子テーマで同じ名前の関数を先に定義して差し替えられるようにするためです(子テーマの functions.php が先に読み込まれるので、親テーマ側を囲んでおくと子テーマの定義が優先されます)。

どこに何を書くかの目安

やりたいこと 書くフック
add_theme_support()、メニュー位置、画像サイズ after_setup_theme
投稿タイプ・タクソノミー・ショートコードの登録 init
CSS・JS の読み込み wp_enqueue_scripts
メインクエリの件数変更など pre_get_posts

動作確認(検証環境と結果)

WordPress 7.1.2(ja)、PHP 8.2.12 の CLI 検証環境で、上のコードを --theme-functions(テーマの functions.php 相当として読み込む機能)で実行しました。この環境は after_setup_theme の先頭で読み込む仕様のため、その時点の状態を確認しています。

  • 読み込み時点で did_action( 'plugins_loaded' ) は 1、did_action( 'init' ) は 0 だった(プラグインより後・init より前)。
  • after_setup_theme に登録した関数は実行され、current_theme_supports( 'post-thumbnails' ) は true。
  • init に登録した関数も実行され、その中の is_user_logged_in() は true を返した。
  • 後から wl1_site_label() を呼ぶと WL1:WP Test、apply_filters( 'excerpt_length', 55 ) は 40 になった。
  • 純 PHP で同じ名前の関数を2回宣言すると Fatal error: Cannot redeclare get_site_label() で止まった。functions.php とプラグインで関数名がぶつかると、同じ理由でサイトが表示されなくなります。

ログは testsfunctions-php-what-is-how-to-write.md にあります。

WordPress の functions.phpの注意点

  • functions.php はテーマを切り替えると読み込まれなくなります。カスタム投稿タイプやショートコードをここに書くと、テーマ変更後に投稿が管理画面から見えなくなったり、本文に [タグ] が文字のまま出たりします。
  • 親テーマを直接編集すると、テーマの更新で上書きされます。配布テーマを使っているなら子テーマの functions.php に書きます(子テーマの作り方と functions.php|親テーマCSSの正しい読み込み)。
  • PHP マニュアルは、PHP だけのファイルでは末尾の ?> を省略するよう勧めています。閉じタグの後の空白や改行が意図しない出力になるのを防ぐためです。
  • 管理画面のテーマファイルエディターで直接編集すると、構文エラーで画面が開けなくなることがあります。FTP などで元に戻せる状態で編集します。

WordPress の functions.phpでよくあるミス

  • ファイル直下で add_theme_support() や register_post_type() を実行し、タイミングの問題で一部が効かない。
  • add_filter() のコールバックで値を return し忘れる(add_filter で return を忘れると|空表示・NULL の原因と対処(準備中))。
  • my_function のような一般的な関数名を付け、プラグインと衝突する。
  • 外部サイトのコードを貼り付ける際に、先頭へ <?php をもう一度書いてしまう。

WordPress の functions.phpのチェックリスト

  • [ ] 処理はフックに登録しているか
  • [ ] 関数名・ハンドル名にテーマ固有の接頭辞を付けたか
  • [ ] フィルターは値を return しているか
  • [ ] テーマ変更後も必要な機能を、プラグインに分けたか
  • [ ] 末尾の ?> を省略したか

WordPress の functions.phpのFAQ(よくある質問)

Q. functions.php に書いたコードが管理画面でも動きますか?
A. 動きます。検証環境の WordPress 7.1.2 の wp-settings.php(740〜757行目)では、有効なテーマ(子テーマなら子と親)の functions.php を管理画面かどうかの条件なしに読み込み、その直後に after_setup_theme を実行しています。フロントだけで動かしたい処理は、wp_enqueue_scripts や template_redirect など、フロントで実行されるフックに登録します。

Q. ファイルが長くなったら?
A. require get_theme_file_path( 'inc/setup.php' ); のように機能ごとにファイルを分けて読み込みます。

Q. コードスニペット系プラグインとの違いは?
A. テーマに依存しない点ではプラグイン側と同じ扱いです。どこに何を書いたかを把握できる方を選びます。

筆者の見解(WordPress の functions.php)

functions.php は手軽なぶん、ネットで見つけたコードを貼り足していくうちに「テーマを変えるとサイトが壊れる」状態になりやすいと考えます。私は、見た目に関わるもの(テーマサポート、CSS の読み込み、テンプレート用の小さな関数)だけを functions.php に置き、投稿タイプ・ショートコード・外部連携は最初から小さな独自プラグインに分ける線引きが、長く運用するサイトでは最も安全だと思います。迷ったら「テーマを変えてもこの機能は必要か」を基準にするのがおすすめです。

WordPress の functions.phpの関連項目

出典(一次情報)

タイトルとURLをコピーしました