★★★ たった "1日" でできるWordPressブログの作り方講座 ★★★ はじめてみる

WordPress子テーマから親テーマの関数を上書きする2つのトリック

初めに断っておきます。
ここで紹介する方法は万能ではありません。

でも関数上書きが必要な場面がありました。

  • 親テーマにhogeという関数がある
  • 子テーマで同名で上書きしたい

条件が整っていれば可能です。

そのトリックをいくつか紹介していきます。

大前提.WP(PHP)で関数の上書きは基本できない

まずこの大前提があることに注意です

>>PHPでは関数の上書きはできない<<

ご存じの通り、WordPressはPHPを基盤にして動いてます。プラグインもテーマもWP本体も全てPHPで書かれていて、PHPなしでは成り立ちません。

そのPHPの言語的な仕様として、関数は上書きできないようになってます。つまり同名関数を再定義できないってことです。

関数を上書きできない

function hoge(){
    echo '元の関数です';
}

function hoge(){
    echo '上書きしたい...';
}

エラーが出て怒られる

PHP Fatal error: Cannot redeclare hoge() (previously declared in /workspace/Main.php:5) in /workspace/Main.php on line 8

このエラーは引数の数・種類を変えたとしても発生します。PHPでは関数のオーバーロードとかもできないんです。

WordPressはこの「PHPでは関数を上書きできない」という制約からは逃れられません。その大前提を忘れずに次の内容をご覧ください。

方法1.プラガブル関数によって上書き

親切なテーマだと初めから上書きに対応してます。

>プラガブル関数による関数上書き<

例えば親テーマにこんな関数あるとしましょう。

例なので内容はあまり気にしないで...

if (!function_exists('parent_func')) {
function parent_func(){
	/// 親テーマの関数
	echo '親テーマの関数';

	if(is_home() || is_front_page()){
		echo 'フロントページだよ';
	}else if(is_category() || is_tax()){
		echo 'カテゴリ・タグページだよ';	
	}else if(is_admin()){
		echo '管理画面ページだよ';
	}else if(is_single()){
		echo '投稿ページだよ';
	}else{
		echo '不明なページ...';
	}
}
}

ポイントは if (!function_exists('parent_func')) {...} のように親側で定義する前に関数定義をチェックしてるところですね。そうすれば子テーマ側で上書きが容易なので

これをプラガブル関数と呼びます。

そして子テーマ側で上書きも簡単です。

子テーマ側で上書きするコード例

function parent_func(){
	/// 子テーマの関数(親を上書き)
	echo '子テーマの関数';

	if(is_home() || is_front_page()){
		echo 'フロントページだよ';
	}else if(is_category() || is_tax()){
		echo 'カテゴリ・タグページだよ';	
	}else if(is_admin()){
		echo '管理画面ページだよ';
	}else if(is_single()){
		echo '投稿ページだよ';
	}else{
		echo '不明なページ...';
	}
}

たったこれだけ

ちなみにプラガブル関数という概念はWordPress1.5.1の頃からあるみたいです。(公式リファレンス : https://wpdocs.osdn.jp/%E3%83%97%E3%83%A9%E3%82%AC%E3%83%96%E3%83%AB%E9%96%A2%E6%95%B0

子テーマのfunctions.phpは親テーマのそれより前に読み込まれるため、親テーマの関数名でガッツリ上書きしちゃって大丈夫です。(普通のPHPではできないこと)

親切なテーマだとプラガブル関数を使えるため、小細工をしなくても関数上書きが簡単にできます。残念なのがそういう親切なテーマは少ないこと・・・

方法2.アクションフックの優先度を使って上書き

これは次の条件に該当するなら使える方法です。

  • 関数がアクションフックから呼ばれている
  • 他関数からは直接呼ばれていない

アクションフック(Action hook)には優先度というものがあり、親テーマ内で関数がフック経由で呼ばれているという場面を想定してます。

例えばこういうコードで考えてみます。

親テーマでの関数定義例

add_action( 'init', 'parent_func', 20 );
function parent_func(){
	/// 親テーマの関数
	echo '親テーマの関数';

	if(is_home() || is_front_page()){
		echo 'フロントページだよ';
	}else if(is_category() || is_tax()){
		echo 'カテゴリ・タグページだよ';	
	}else if(is_admin()){
		echo '管理画面ページだよ';
	}else if(is_single()){
		echo '投稿ページだよ';
	}else{
		echo '不明なページ...';
	}
}

WordPressではadd_action関数で特定条件(例 : WP初期化時・投稿保存時)にアクションを登録でき、上コードでは 'init' が起きたときに parent_func() を優先度20で呼び出してます。

このフックを削除する

/// 親テーマ関数のフック削除
remove_action('init', 'parent_func');

子テーマで代わりの関数を登録

add_action( 'init', 'child_parent_func', 20 );
function child_parent_func(){
	/// 子テーマの関数(上書き)
	echo '子テーマの関数';

	/// 代わりのコード内容...
}

上コードみたいに登録済みの親テーマ関数をremove_action関数で削除し、子テーマでその代わりになる関数を作ってフックに登録するみたいな感じです

この方法が使える場面は少なそう

でも参考として一応載せておきます。

まとめ - 関数上書きするベストプラクティスはない

↑ 結論を書いちゃうとこうなります (-_-;)

でもここまでで紹介した方法でできることもあるかも

どちらも万能な方法ではありません。

もし無理なら上書き以外のアプローチを探してください。

The following two tabs change content below.

フク郎

昔はプログラミングに熱中していたが、ブログとWordPressに興味を持ち始め今はサイト・ブログ作りが生きがい。自分の「好き」をブログに変えたい、情報発信したい人に役立つWordPress術・サイト構築術を発信中。一日一歩楽しんでブログ構築できるように読みやすい&楽しい記事作りを心がけています。