functions.phpで制御しきれない部分を子テーマで補う方法|現場で使える実践テクニック

functions.phpで制御しきれない部分を子テーマで補う方法|現場で使える実践テクニック
C
クリオ
Web制作ディレクター / フロントエンジニア

こんにちは!
今日は「WordPressの子テーマで親テーマのfunctions.phpをうまく上書きする方法」について解説します。

親テーマのfunctions.phpが上書きされない理由

僕も最初めっちゃ戸惑ったんですよ。
子テーマのfunctions.phpを作って、親テーマの関数を上書きしようとしたら、全然効かへんかった。
理由はシンプルで、functions.phpはテンプレートファイルと違って「テンプレート階層」の対象やないんです。

WordPressは読み込み順序が決まってます。
子テーマのfunctions.phpも親テーマのfunctions.phpも、どちらも読み込まれるんですよ。
でも読み込まれる順序は「親テーマ → 子テーマ」です。
つまり、両方の関数定義が実行されてしまうわけです。

もし親テーマでfunction my_custom_function() { ... }っていう関数があったら、子テーマで同じ名前の関数を定義しても、既に親テーマで定義済みだから、子テーマのコードは実行されへんってわけなんです。

子テーマで関数を安全に置き換える実装方法

では、どうするか。
ほんま大事なのは「条件付きで関数定義を制御する」ことなんですよ。

親テーマのfunctions.phpがこんな感じやったとしましょう:

<?php
function my_theme_header() {
  echo '親テーマのヘッダー';
}
add_action( 'wp_body_open', 'my_theme_header' );
?>

これを子テーマで上書きしたい場合は、子テーマのfunctions.phpでこう書くといいですよ:

<?php
// 親テーマの関数が定義されている場合のみ、処理をフック
if ( function_exists( 'my_theme_header' ) ) {
  remove_action( 'wp_body_open', 'my_theme_header' );
}

function my_theme_header() {
  echo '子テーマでカスタマイズしたヘッダー';
}
add_action( 'wp_body_open', 'my_theme_header' );
?>

ポイントはremove_action()で親テーマのアクションをいったん外してから、子テーマの新しい関数を登録するってことです。
こうすることで、意図した処理だけが実行されるわけです。

もっと簡潔にしたい場合は、親テーマの関数を最初からif ( ! function_exists() )で条件付けしてくれてたら、子テーマで先に定義できます。
親テーマがこう書いてるなら:

<?php
if ( ! function_exists( 'my_theme_header' ) ) {
  function my_theme_header() {
    echo '親テーマのヘッダー';
  }
}
add_action( 'wp_body_open', 'my_theme_header' );
?>

子テーマで同じ関数を先に定義すれば、親テーマの定義はスキップされます。
これはめっちゃクリーンな方法やん。

現場でよくある失敗パターンと対策

現場でよく見るのは、ほんまこれなんです。
子テーマで関数をコピペして変更したけど、何も変わらへんって相談を受けることめっちゃあります。

もう一つ大事なのが「フックのタイミング」です。
remove_action()でアクションを外すなら、それより前に親テーマが実行されたら意味ないんですよ。
だから子テーマのfunctions.phpで処理する場合、確実に親テーマより後に実行されるように、wp_loadedとかinitフックを使うといいですよ。

それと、もし親テーマがフィルターを使ってたら話は別です。
フィルターの場合はadd_filter()で簡単に上書きできます。
例えば親テーマがapply_filters( 'my_theme_title', $title )って処理してるなら、子テーマでadd_filter( 'my_theme_title', 'my_custom_title_function' )で対応できるわけです。
これはアクションより融通が効きやすいんですよ。

あと、デバッグのコツとしては、子テーマで変更が効いてるか確認するときに、一度関数の中にerror_log()を入れてログで確認するといいですよ。
実際に実行されてるか確認できるので、めっちゃ便利です。

まとめ

子テーマで親テーマのfunctions.phpをカスタマイズするには、ただコピペするだけじゃなくて、きちんとした手順が必要やってわけです。

remove_action()add_action()の組み合わせを使うか、親テーマが最初からif ( ! function_exists() )で条件付けしてくれてるのを活用するか。
もしくはフィルターを使って柔軟に値を変更するか。
この3つの方法を場面に応じて使い分けるといいですよ。

テーマ開発は最初めっちゃ試行錯誤が必要ですけど、こういう基本をおさえておくと、後々の改修がほんまに楽になります。
ぜひ実装してみてください。

Web制作で困ったことがあったら、またこのブログを覗いてくださいね!

― クリオ