2026年10月8日

2026年10月8日

WordPressテーマ開発の基本|functions.phpに書く初期設定・読み込み・メニュー登録

自作テーマの functions.php には、テーマの機能を有効にする設定(after_setup_theme)、CSS と JavaScript の読み込み(wp_enqueue_scripts)、メニューやウィジェットエリアの登録をまとめて書きます。この記事では、クラシックテーマを一から作る前提で、functions.php に最初に書くべき内容を順番に組み立て、ファイルが大きくなったときの分け方と、編集で画面が真っ白にならないための注意点までを説明します。

functions.php の役割と読み込まれるタイミング

functions.php は、テーマが有効なときにだけ毎回のリクエストで読み込まれる PHP ファイルです。テンプレートのように画面を出力する場所ではなく、「WordPress の動きに処理を差し込む」ための場所と考えると整理しやすくなります。

読み込みの順番は次のとおりです。

  1. 有効なプラグインが読み込まれる
  2. 子テーマがあれば子テーマの functions.php、続いて親テーマの functions.php
  3. after_setup_theme アクション
  4. init アクション、その後にテンプレートの表示

このため、functions.php の中でいきなり処理を書くのではなく、決められたフック(アクション・フィルター)に関数を登録するのが基本の書き方です。直接書いた処理は「まだ WordPress の準備が終わっていない段階」で動くことがあり、関数が未定義だったり、設定が反映されなかったりする原因になります。

なお、テーマとして認識されるのに最低限必要なのは、テーマ名などを書いた style.css と index.php です(クラシックテーマの場合)。テンプレートでは <head> 内に wp_head()、</body> の直前に wp_footer()、<body> の直後に wp_body_open() を置きます。これを忘れると、後で登録する CSS や JavaScript が出力されません。

テーマ機能を有効にする(after_setup_theme)

タイトルタグやアイキャッチ画像など、テーマが対応している機能を WordPress に伝えるのが add_theme_support() です。after_setup_theme に登録した関数の中で呼び出します。

<?php
// functions.php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

function mytheme_setup() {
	// <title> を WordPress に出力させる
	add_theme_support( 'title-tag' );

	// アイキャッチ画像
	add_theme_support( 'post-thumbnails' );

	// 検索フォームやコメント欄を HTML5 のマークアップで出力
	add_theme_support( 'html5', array( 'search-form', 'comment-form', 'comment-list', 'gallery', 'caption', 'style', 'script' ) );

	// カスタムロゴ(カスタマイザーから設定)
	add_theme_support( 'custom-logo', array(
		'height'      => 80,
		'width'       => 240,
		'flex-height' => true,
		'flex-width'  => true,
	) );

	// 埋め込みコンテンツのレスポンシブ対応
	add_theme_support( 'responsive-embeds' );

	// ナビゲーションメニューの位置
	register_nav_menus( array(
		'primary' => __( 'メインメニュー', 'mytheme' ),
		'footer'  => __( 'フッターメニュー', 'mytheme' ),
	) );
}
add_action( 'after_setup_theme', 'mytheme_setup' );

ポイントは次の3つです。

  • title-tag:テンプレートに <title> を手書きせず、WordPress に任せます。SEO 系プラグインがタイトルを変えるときも、この仕組みを通して反映されます。
  • 関数名の接頭辞:mytheme_ のようにテーマ固有の接頭辞を付けます。プラグインと関数名がぶつかると致命的エラーで画面が止まるためです。
  • 翻訳関数:__( '文字列', 'テキストドメイン' ) で囲んでおくと、後から翻訳ファイルで表示を差し替えられます。

テンプレート側では、メニューは wp_nav_menu( array( 'theme_location' => 'primary' ) );、ロゴは the_custom_logo(); で出力します。

CSS と JavaScript を読み込む(wp_enqueue_scripts)

header.php に <link> や <script> を直接書くと、プラグインとの重複読み込みや順番の問題が起きやすくなります。WordPress には読み込みを管理する仕組みがあるので、wp_enqueue_scripts アクションで登録します。

function mytheme_assets() {
	$theme_version = wp_get_theme()->get( 'Version' );

	wp_enqueue_style(
		'mytheme-style',
		get_stylesheet_uri(),
		array(),
		$theme_version
	);

	$js_path = get_theme_file_path( 'assets/js/main.js' );
	wp_enqueue_script(
		'mytheme-main',
		get_theme_file_uri( 'assets/js/main.js' ),
		array(),
		file_exists( $js_path ) ? filemtime( $js_path ) : $theme_version,
		array(
			'in_footer' => true,
			'strategy'  => 'defer',
		)
	);
}
add_action( 'wp_enqueue_scripts', 'mytheme_assets' );

第4引数のバージョンは、ブラウザのキャッシュ対策です。値が変わると URL の ?ver= が変わり、古いファイルが使われ続ける問題を避けられます。開発中はファイルの更新時刻(filemtime)を使うと、編集のたびに自動で切り替わります。

第5引数に配列で strategy を渡す書き方は WordPress 6.3 で追加されました。defer を指定すると、HTML の解析を止めずにスクリプトを読み込めます。古いバージョンでは配列ではなく true(フッターで読み込む)を渡す書き方になるため、対応バージョンをテーマの説明に書いておくと親切です。

get_theme_file_uri() と get_theme_file_path() は、子テーマに同じパスのファイルがあればそちらを優先して返します。子テーマでの上書きを想定するなら、get_template_directory_uri() より扱いやすい関数です。

ウィジェットエリアとコンテンツ幅

サイドバーやフッターにウィジェットを置けるようにするには、widgets_init アクションで register_sidebar() を呼びます。

function mytheme_widgets() {
	register_sidebar( array(
		'id'            => 'sidebar-1',
		'name'          => __( 'サイドバー', 'mytheme' ),
		'before_widget' => '<section id="%1$s" class="widget %2$s">',
		'after_widget'  => '</section>',
		'before_title'  => '<h2 class="widget-title">',
		'after_title'   => '</h2>',
	) );
}
add_action( 'widgets_init', 'mytheme_widgets' );

テンプレートでは if ( is_active_sidebar( 'sidebar-1' ) ) { dynamic_sidebar( 'sidebar-1' ); } のように、ウィジェットが置かれているときだけ出力します。id は後から変えると配置済みのウィジェットが外れるため、最初に決めたら変えないようにします。

埋め込み動画などの最大幅を伝える $content_width も、古くからある設定として残っています。本文エリアの幅に合わせて after_setup_theme の中で $GLOBALS['content_width'] = 760; のように設定しておくと、埋め込みの幅がはみ出しにくくなります。

functions.php が大きくなったら分割する

機能を足していくと functions.php は数百行になりがちです。役割ごとにファイルを分けて読み込むと、修正箇所を探しやすくなります。

// functions.php の末尾
$mytheme_includes = array(
	'inc/setup.php',
	'inc/assets.php',
	'inc/template-tags.php',
);
foreach ( $mytheme_includes as $file ) {
	require_once get_theme_file_path( $file );
}

分けるときの目安は「設定」「読み込み」「テンプレート用の関数」「管理画面の調整」です。

もう一つ大事なのが、テーマに書くべきでないものを入れないことです。カスタム投稿タイプ、ショートコード、外部サービスとの連携など、テーマを切り替えても残したい機能は、プラグイン(自作なら mu-plugins でも可)に置きます。テーマに書くと、デザインを変えた途端に投稿が管理画面から見えなくなる、本文にショートコードの文字列がそのまま出る、といった問題が起きます。

編集で画面を真っ白にしないための注意点

functions.php は毎回読み込まれるため、1文字の書き間違いでサイト全体が表示されなくなります。次の点を習慣にしてください。

  • 本番で直接編集しない:ステージング環境かローカル環境で動作を見てから反映します。編集前にはファイルのバックアップを取ります。
  • 構文チェックを通す:サーバーに PHP が入っていれば php -l functions.php で文法エラーを事前に見つけられます。
  • **閉じタグ ?> を書かない**:ファイル末尾の ?> の後に空白や改行が入ると「headers already sent」の警告が出ることがあります。PHP だけのファイルでは閉じタグを省略するのが一般的です。
  • エラーはログで確認する:wp-config.php で WP_DEBUG と WP_DEBUG_LOG を有効にし、WP_DEBUG_DISPLAY を false にすると、画面に出さずに wp-content/debug.log へ記録できます。確認が終わったら元に戻します。
  • 管理画面に入れなくなったら:FTP やファイルマネージャーで、直前に編集したファイルを戻すか、テーマのフォルダー名を変えて既定のテーマに切り替えます。

管理画面のテーマファイルエディターは手軽ですが、保存した瞬間に本番へ反映されます。エディター自体を無効にしたい場合は wp-config.php に define( 'DISALLOW_FILE_EDIT', true ); を書く方法があります。

ブロックテーマとの違い

ここまではクラシックテーマの書き方です(2026年10月現在、WordPress の既定テーマはブロックテーマです)。ブロックテーマでは、色やフォント、レイアウト幅などの多くを theme.json で設定し、テンプレートも HTML ファイルで作ります。そのため functions.php に書く量は減りますが、スクリプトの読み込みやブロックスタイルの登録など、PHP で行う処理は引き続き functions.php に書きます。どちらの方式で作るかを最初に決めてから設計すると、後から書き直す手間を減らせます。

配布されているテーマを改造したい場合は、テーマを直接編集せず子テーマを作ってください。親テーマを更新すると、直接加えた変更は上書きされて消えます。

まとめ

  • functions.php は「画面を出す場所」ではなく、フックに処理を登録する場所です。
  • テーマ機能は after_setup_theme で add_theme_support() と register_nav_menus() を使って有効にします。
  • CSS・JavaScript は wp_enqueue_scripts で読み込み、バージョン引数でキャッシュを切り替えます。strategy 引数は WordPress 6.3 以降です。
  • 関数には接頭辞を付け、大きくなったら inc/ に分割します。カスタム投稿タイプなどはプラグイン側に置きます。
  • 編集はバックアップとステージングでの確認を先に行い、エラーは debug.log で確かめます。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲