2026年5月20日

2026年5月20日

子テーマのfunctions.phpでWordPressをカスタマイズする方法

はじめに

子テーマの functions.php はWordPressカスタマイズの要です。親テーマの functions.php に上書きされることなく、フックの追加・関数の上書き・独自機能の実装が可能です。正しい書き方を覚えることでメンテナブルなサイトを構築できます。

症状・原因

  • 子テーマのfunctions.phpに書いたコードが動かない
  • 親テーマの関数を上書きしたいが方法がわからない
  • functions.phpにどんな処理を書くべきかわからない
  • フックの使い方がわからない

解決手順

ステップ1:functions.phpの基本構造

<?php
// wp-content/themes/my-child-theme/functions.php

// 子テーマのfunctions.phpは親テーマより「後」に読み込まれる
// → 親テーマのフックを上書き・追加できる

// ================================
// 親テーマのスタイルを読み込む(必須)
// ================================
add_action('wp_enqueue_scripts', function(): void {
    wp_enqueue_style(
        'parent-style',
        get_template_directory_uri() . '/style.css'
    );
    wp_enqueue_style(
        'child-style',
        get_stylesheet_directory_uri() . '/style.css',
        ['parent-style'],
        wp_get_theme()->get('Version')
    );
});

ステップ2:フックでWordPressの動作を変更する

// ================================
// タイトルタグをカスタマイズ
// ================================
add_filter('document_title_separator', function(): string {
    return '|';
});

// ================================
// 抜粋の文字数を変更(デフォルト55語)
// ================================
add_filter('excerpt_length', function(): int {
    return 120;
});

// ================================
// 抜粋の「...」を変更
// ================================
add_filter('excerpt_more', function(): string {
    return '…<a href="' . get_permalink() . '">続きを読む</a>';
});

// ================================
// ログイン後のリダイレクト先を変更
// ================================
add_filter('login_redirect', function(string $redirect_to, string $requested_redirect_to, WP_User $user): string {
    if (in_array('administrator', $user->roles, true)) {
        return admin_url();
    }
    return home_url('/mypage/');
}, 10, 3);

ステップ3:管理画面をカスタマイズする

// ================================
// 管理バーを非表示(購読者のみ)
// ================================
add_action('after_setup_theme', function(): void {
    if (!current_user_can('edit_posts')) {
        add_filter('show_admin_bar', '__return_false');
    }
});

// ================================
// ダッシュボードのウィジェットを削除
// ================================
add_action('wp_dashboard_setup', function(): void {
    remove_meta_box('dashboard_quick_press', 'dashboard', 'side');
    remove_meta_box('dashboard_primary', 'dashboard', 'side');
});

// ================================
// 管理画面のフッターテキストを変更
// ================================
add_filter('admin_footer_text', function(): string {
    return '<span>管理画面 | <a href="' . home_url() . '">' . get_bloginfo('name') . '</a></span>';
});

ステップ4:親テーマの関数を上書きする

// ================================
// pluggable関数の上書き(if !function_exists パターン)
// ================================
if (!function_exists('parent_theme_posted_on')) {
    function parent_theme_posted_on(): void {
        // 親テーマの投稿日表示を上書き
        echo '<time datetime="' . get_the_date('c') . '">';
        echo get_the_date('Y年n月j日');
        echo '</time>';
    }
}

// ================================
// フックの削除 → 再追加で上書き
// ================================
add_action('after_setup_theme', function(): void {
    // 親テーマのアクションを削除
    remove_action('wp_head', 'parent_theme_add_meta_tags');

    // 独自のメタタグを追加
    add_action('wp_head', function(): void {
        echo '<meta name="theme-color" content="#0073aa">' . PHP_EOL;
    });
}, 11); // 親テーマより後(priority 11)で実行

ステップ5:よく使う実装パターン

// ================================
// カスタムメニューを追加
// ================================
add_action('after_setup_theme', function(): void {
    register_nav_menus([
        'header-menu'  => 'ヘッダーメニュー',
        'footer-menu'  => 'フッターメニュー',
        'sidebar-menu' => 'サイドバーメニュー',
    ]);
});

// ================================
// ウィジェットエリアを追加
// ================================
add_action('widgets_init', function(): void {
    register_sidebar([
        'name'          => 'カスタムサイドバー',
        'id'            => 'custom-sidebar',
        'before_widget' => '<div class="widget %2$s">',
        'after_widget'  => '</div>',
        'before_title'  => '<h3 class="widget-title">',
        'after_title'   => '</h3>',
    ]);
});

// ================================
// 画像サイズを追加
// ================================
add_action('after_setup_theme', function(): void {
    add_image_size('custom-thumbnail', 400, 300, true);
    add_image_size('custom-hero',      1200, 600, true);
});

ステップ6:WP-CLIでフック一覧を確認する

# 登録されているアクションフックを確認
wp eval "
global \$wp_filter;
foreach (array_keys(\$wp_filter) as \$hook) {
    echo \$hook . PHP_EOL;
}" | grep -E "^(wp_head|wp_footer|init|wp_enqueue)"

# 子テーマのfunctions.phpが読み込まれているか確認
wp eval "echo get_stylesheet_directory() . PHP_EOL;"
wp eval "echo locate_template('functions.php') . PHP_EOL;"

# テーマ設定を確認
wp theme get $(wp theme list --status=active --field=name) --format=json

注意事項

  • functions.php の先頭に タグを書き、末尾の ?> は省略してください(空白文字混入によるエラー防止)
  • 親テーマの関数を上書きするには if (!function_exists()) パターンを使います。ただし親テーマが pluggable として設計している必要があります
  • 重い処理は適切なフックで遅延実行し、全ページでの実行は避けてください

まとめ

子テーマの functions.php では add_action/add_filter でフックを追加し、remove_action/remove_filter で親テーマの動作を変更します。if (!function_exists()) パターンで関数を上書きでき、カスタムメニュー・ウィジェットエリア・画像サイズの追加もここで行います。

お気軽にご相談ください