【WordPress】保守に強い子テーマ 〜壊れても困らない構成術〜

こんにちは。新卒入社半年、WordPress の実務にも触り始めたばかりの新人エンジニアです。

フロントエンジニア

がしま

WordPress のカスタマイズ?なんだいそれは…。

といった感じで、当時の私は「とりあえず動けばいいでしょ」という感覚でした。

  • CSS は「追加CSS」で上書き!
  • PHP は functions.php に追記すれば良さそう?
  • プラグインの動きを少し変えたいときは、コードの一部を書き換えれば済むじゃん!

今振り返ると、かなり危うい考え方だったと思います。

ロージー

弊社マスコットキャラクター

ロージー

(保守はどうするしゅこ…?)

フロントエンジニア

がしま

(考えていなかった…)

当然、上司にこう聞かれることになります。

「このまま自動アップデートしても壊れない?」

「保守の観点は?」

その瞬間に気づいたのは、動くことと保守できることは別 だということでした。

そこで私は、

  • スニペットを散らばらせない
  • 親テーマやプラグイン本体を直接書き換えない
  • 「どこを見ればいいか」が一目で分かる

そんな状態を目指して、子テーマの中身を整理し直すことにしました。

ここからは、子テーマの前提を軽く整理し、ディレクトリ構成を確認したうえで、CSS / JS / PHP の分割と読み込み方を順に見ていきます。

① そもそも子テーマとは?

WordPress には「親テーマ」と「子テーマ」があります。

種類 役割 更新時
親テーマ サイト全体のデザイン・機能を提供する「本体」 更新でファイルが上書きされる
子テーマ 変更や追加コードを置くための「カスタマイズ用領域」 更新では消えない

親テーマを直接編集すると、テーマ更新のたびに変更が消えるため、実務では子テーマにカスタマイズをまとめることが一般的です。
本記事では、その前提のもとで、「子テーマ側の中身をどう整理するか」にフォーカスして解説していきます。

参考:https://developer.wordpress.org/themes/advanced-topics/child-themes/

② おすすめディレクトリ構成(保守性重視)

ここでは、mytheme-child という名前で作成した子テーマフォルダを例にします。
この中に、CSS・JS・PHP などのファイルがどんどん増えていくことを想定して、
最初から置き場所を分けておきます。

■ディレクトリ構成の例

mytheme-child/
│
├─ style.css        ← 子テーマの基本情報・最低限の初期スタイル
├─ functions.php    ← 読み込み専用(各処理を inc/ に振り分けるハブ)
│
├─ assets/          ← 静的ファイル(CSS / JS / 画像)
│   ├─ css/         ← 共通・ページ単位の CSS(例:common.css / page-home.css)
│   ├─ js/          ← 挙動調整用 JS(例:menu-toggle.js)
│   └─ images/      ← ロゴ・バナー画像など
│
└─ inc/             ← PHP(追加処理・機能のまとまり)
    ├─ enqueue/     ← CSS・JS を登録する専用フォルダ
    │    ├─ enqueue-styles.php   ← CSS の読み込み処理
    │    └─ enqueue-scripts.php  ← JS の読み込み処理
    │
    ├─ plugins/     ← 既存プラグインの挙動調整(変更点をここに集約)
    │    ├─ plugin-adjust-search.php
    │    └─ plugin-adjust-login.php
    │
    └─ view/        ← 表示に関わる処理(HTML 生成・UI 調整)
         ├─ header-banner.php
         └─ breadcrumb.php

実際のロジックは inc/assets に細かく分割し、
functions.php は「どのファイルを読み込むか」だけを書く方針です。

②-1. functions.php は “目次” として使う

functions.phpにロジックをどんどん書き足していくと、
「どこに何があるか分からない巨大ファイル」になりがちです。
そこで、functions.php には処理を書かず、「どのファイルを読むか」を宣言するだけにしました。

■コード1:子テーマでの読み込み専用 functions.php の例

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

// =======================
// 基本セットアップ
// =======================
add_editor_style(); // エディタ用スタイルを適用
define( 'CHILD_THEME_DIR', get_stylesheet_directory() );
define( 'CHILD_THEME_URI', get_stylesheet_directory_uri() );

// =======================
// CSS / JS 読み込み設定
//   実処理は inc/enqueue/ に分割
// =======================
require_once CHILD_THEME_DIR . '/inc/enqueue/enqueue-styles.php';
require_once CHILD_THEME_DIR . '/inc/enqueue/enqueue-scripts.php';

// =======================
// プラグイン調整(追加の補正ロジック)
// =======================
require_once CHILD_THEME_DIR . '/inc/plugins/plugin-adjust-search.php';
require_once CHILD_THEME_DIR . '/inc/plugins/plugin-adjust-login.php';

// =======================
// 表示系の調整(UI に関わる処理)
// =======================
require_once CHILD_THEME_DIR . '/inc/view/header-banner.php';
require_once CHILD_THEME_DIR . '/inc/view/breadcrumb.php';

functions.php には処理を書かず、「どのファイルを読むか」を列挙するだけの
“読み込み専用” ファイルとして使います。
実際のロジックは inc/ 以下の PHP や assets 内の CSS / JS に分割して閉じ込めておくイメージです。

③ CSS:全ページ同じ調整ではなく、ページ単位で読み分ける

「追加 CSS」を多用すると、全ページに同じ調整が当たってしまい、
副作用が発生した際に原因を追いづらくなりますが、
子テーマなら、共通 CSS とページ専用 CSS を分けて読み込むことで整理しやすくなります。

■コード2:共通 CSS とページ別 CSS を読み分ける例

// functions.php から読み込まれる inc/enqueue-styles.php

add_action( 'wp_enqueue_scripts', function () {
    $base      = CHILD_THEME_URI . '/assets/css';
    $base_path = CHILD_THEME_DIR . '/assets/css';

    // 1) 子テーマ本体(style.css)
    wp_enqueue_style(
        'child-theme-style',
        get_stylesheet_uri(),
        [],
        filemtime( get_stylesheet_directory() . '/style.css' )
    );

    // 2) 全ページ共通の分割 CSS
    foreach ( [ 'common.css', 'forum.css' ] as $file ) {
        $path = $base_path . '/' . $file;
        if ( ! file_exists( $path ) ) {
            continue;
        }
        $handle = 'child-' . str_replace( '.css', '', $file );
        wp_enqueue_style(
            $handle,
            $base . '/' . $file,
            [ 'child-theme-style' ],
            filemtime( $path )
        );
    }

    // 3) 特定ページだけの調整(例:フォーラムのユーザー詳細)
    $current_url = $_SERVER['REQUEST_URI'] ?? '';
    if ( strpos( $current_url, '/forums/users/' ) !== false ) {
        $file = 'user-page.css';
        $path = $base_path . '/' . $file;
        if ( file_exists( $path ) ) {
            $handle = 'child-' . str_replace( '.css', '', $file );
            wp_enqueue_style(
                $handle,
                $base . '/' . $file,
                [ 'child-theme-style' ],
                filemtime( $path )
            );
        }
    }
}, 20);

この構成にしておくと、どの URL でどの CSS が効いているかが一目で分かり、
影響範囲が URL 単位で切れているぶん、デバッグもしやすくなります。

④ JS:CSS で直せないところだけ、局所的に補正する

CSS で消せない要素や、PHP が触れない部分は、JS で “必要なところだけ” そっと動かす形にします。

■コード3:パンくずを移動させる JS の例

// assets/js/move-breadcrumb.js

document.addEventListener('DOMContentLoaded', () => {
  const bc = document.getElementById('breadcrumb');
  const content = document.getElementById('content');

  // 要素が存在しないケースに備えつつ、多重実行を防止
  if (bc && content && !bc.dataset.moved) {
    content.parentNode.insertBefore(bc, content);
    bc.dataset.moved = '1';
  }
});

ポイントは、ID で対象をきちんと限定することと、
「一度動かしたら終わり」にするために data-* 属性で多重実行防止することです。
同名クラスが増えたり、他の JS が動いていても、影響範囲を絞っておけば “巻き込み事故” を減らしやすくなります。

⑤ PHP:プラグイン本体を書き換えず、子テーマ側で補正する

プラグイン本体のコードを直接編集すると、更新で上書きされて調整内容が消えてしまうリスクがあります。
そこで、補正は子テーマ内の inc/plugins/ にまとめます。

inc/plugins/
└─ plugin-adjust-search.php
   plugin-adjust-login.php
   plugin-adjust-breadcrumb.php

■コード4:パンくず出力をフックで差し込む例

// inc/plugins/plugin-adjust-breadcrumb.php

add_action(
    'wp_body_open',
    function () {
        // プラグインが無効な場合は何もしない
        if ( ! function_exists( 'my_forum_breadcrumb' ) ) {
            return;
        }

        echo '<nav id="breadcrumb">' . my_forum_breadcrumb() . '</nav>';
    },
    5
);

プラグイン本体には一切触らず、用意されている関数(ここでは my_forum_breadcrumb()
をフックから呼び出すことで、「このサイト専用の出力位置の調整」だけを子テーマ側に閉じ込めることができます。

⑥ 更新で起きやすい不具合と影響範囲

テーマやプラグインを更新したとき、影響が出やすいポイントを整理すると次の通りです。

技術領域 更新で起きがちなこと よくある壊れ方
CSS クラス名や HTML 構造が変わる レイアウトや色が崩れる
JS(DOM 補正) 取っている ID / クラスの要素が変わる ボタンが効かない・動きが消える
PHP(フック) 使っているフックが変わる・消える 独自出力が出なくなる

本記事で紹介した子テーマ構成にしておくと、例えばアップデート後に不具合が出たときに、

  • 見た目だけ崩れた → assets/css を見る
  • 「動き」がおかしい → assets/js を見る
  • 出力そのものがおかしい → inc/plugins / inc/view を見る

…と、「まずどこから確認するか」を絞りやすくなります。

⑦ まとめ:壊れないサイトより、「直しやすいサイト」を

本記事では、子テーマの中身を用途ごとに整理し、更新の影響を受けにくくする考え方を紹介しました。

壊れても「まずここを見ればいい」が分かる構造

にしておくと、アップデート後の確認もスムーズです。
あなたのサイト運用のヒントになれば幸いです。

ところで

弊社ロジカルスタジオでは、一緒に働く仲間を募集しています!
記事を読んで「一緒に開発してみたい」と思っていただけたら、ぜひ採用ページも覗いてみてください。