WordPressで「この関数が存在しなかったら..」という条件を加えるおまじない?的な処理。
ユーザー定義関数(自身で作成した関数)を以下のコードで囲むことで、どこかに同じ〇〇という関数が存在していたら処理しないようにするもので、予期せぬエラーを回避するために使うケースが多いと思います。
if ( !function_exists( '〇〇' ) ){
function 〇〇(){
----ここにコード----
}
}
確かにエラーでストップすることはなくなるのですが、使い方を間違えると、思ったように動作しないことがあるので注意が必要です。
プラグインとテーマのどちらが優先されるか?
同じ処理をプラグインとテーマで同時にさせた時にどうなるのか?をテストする場合の簡単なコードを紹介しつつ確認してみてください。
まずは有効化しているテーマのfunctions.php等へ以下のコードを追加します。
if ( !function_exists( 'pwcn_priority_test' ) ){
function pwcn_priority_test(){
?>
<p>テーマ側で出力したもの</p>
<?php
}
}
add_action('wp_head','pwcn_priority_test');
追加後、サイトを表示させてみると、ページの冒頭に「テーマ側で出力したもの」という文字列が表示されるはずです。
次に以下のコードを自作プラグインのプログラムへ追加します。
if ( !function_exists( 'pwcn_priority_test' ) ){
function pwcn_priority_test(){
?>
<p>プラグイン側で出力したもの</p>
<?php
}
}
add_action('wp_head','pwcn_priority_test');
そしてもう一度サイトを表示させると、文字列が「プラグイン側で出力したもの」と変化するはずです。
同じ「wp_head」というフックを使っていることから、フックの優先度が同じなので、WordPressの読み込みは、「プラグイン」→「テーマ」の順になっていることが分かります。
つまり、テーマ側の処理は既に関数が存在しているので無視されるということです
どうしてもテーマ側の処理をさせたいときは
順序(優先度)はわかったものの、これではプラグイン側の処理をテーマ側で書き換えるということはできない!となってしまいますね。
それでは困る場合があると思いますので、以下のようにして対処すると解決できます。
- プラグイン側の処理を削除(停止)する
- 同じプログラムを別のユーザー定義関数としてテーマ側で作成して処理させる
前述のコードの例の場合、テーマ側のfunctions.phpへ追加したコードを一旦削除して、以下のコードを追加してください。
function remove_pwcn_priority_test(){
remove_action( 'wp_head' , 'pwcn_priority_test' );
}
add_action('after_setup_theme', 'remove_pwcn_priority_test' );
このコードによって、プラグイン側で「add_action」で処理していたものを一旦停止することができます。
ただし、ユーザー定義関数(上記の場合は「pwcn_priority_test」)自体がなくなったわけではないので、テーマ側で同じユーザー定義関数を書いても無視されてしまいますから、以下のように別のユーザー定義関数名へ変更(「pwcn_priority_test_02」)してプログラムを書きなおします。
if ( !function_exists( 'pwcn_priority_test_02' ) ){
function pwcn_priority_test_02(){
?>
<p>テーマ側で出力したもの</p>
<?php
}
}
add_action('wp_head','pwcn_priority_test_02');
余談ですが、確かにこのようにすることで単純なものであれば置き換えが可能ではあるものの、他の引数やコールバック関数を引っ張ってきて処理するなど複雑なものになると置き換えが不可能な場合もあるため、プラグインでは各所に変更させるためのフック(フィルターフック)を用意して、その部分だけを書き換えるということができるようになっているのです。
フィルターフックについては以下で説明していますのでついでにどうぞ。
同じコールバック関数をテーマ・プラグイン両方に記述する際の注意
例えば以下のような条件を指定する関数があったとします。
これはis_mobile()というユーザー定義関数を追加して、タブレットをパソコンとして判定させるためのものなのですが、これを行うためのプログラムをプラグイン側、テーマ側両方に追加する場合(追加する可能性がある場合)には、両方に重複チェックを入れておかないと、テーマを有効化した状態でプラグインを有効化しようとしたとき、「重大なエラーが..」となって有効化できなくなります。
これは、前項のテーマとプラグインのどちらが優先されるかという話と同じで、例えばテーマ側のみに重複チェックが入っている(または入っていない)と、存在しているものに対して同じユーザー定義関数を追加しようとしたりするなどの不都合が発生するからです。
親テーマと子テーマのどちらが優先されるか?
これも同じようなコードで簡単にテストできます。
前項のコードを削除して、以下のコードを親テーマへ追加します。
if ( !function_exists( 'pwcn_priority_test' ) ){
function pwcn_priority_test(){
?>
<p>親テーマ側で出力したもの</p>
<?php
}
}
add_action('wp_head','pwcn_priority_test');
そして、子テーマへ以下のコードを追加します。
if ( !function_exists( 'pwcn_priority_test' ) ){
function pwcn_priority_test(){
?>
<p>子テーマ側で出力したもの</p>
<?php
}
}
add_action('wp_head','pwcn_priority_test');
すると..まあ想像できているでしょうが、子テーマのコードが優先されることが確認できるはずです。
おまけ 2重出力に注意
ここまでは関数に対する処理について書いてきましたが、それを処理させるフックについての注意事項です。
上書きできないからと、以下のコードに優先度を設けたらどうなるでしょう。
add_action('wp_head','pwcn_priority_test',999);
これを親テーマ・子テーマ(またはテーマ・プラグイン)のどちらかに追加すると..別のアクションとして処理されるので、2重に出力されます。
フックに優先度を設ける際には優先度を指定しない、もしくは合わせるようにしないと不都合が出るので、注意しましょう。
コメントを残す