WordPress子テーマでstyle.cssは上書き継承、functions.phpは継承されるのに、JavaScriptは継承される仕組みがないのでPHPで継承システムを作る方法

子テーマでJavaScriptを自動継承できる仕組みをPHPで作ってみたので紹介です。

正直、他にもっと良い方法があるのかもしれませんが、今の自分に思いつく精一杯です。

photo by Christopher Ross

スポンサーリンク
レクタングル(大)広告

子テーマでJavaScriptファイルは自動継承されない

WordPressの子テーマを使用するとき、子テーマのスタイルシートstyle.cssによって以下のように親テーマのstyle.cssを呼び出すことができます。

@import url("../親テーマディレクトリ/style.css");

このように呼び出すことで、親テーマのスタイルを継承し、上書きすることができます。

同様に子テーマでfunctions.phpを作成すると、親テーマのfunctions.phpが、まず先に呼び出されます。そして関数を上書きすることはできませんが、子テーマのfunctions.phpが呼び出されます。

では、親テーマで使用されているJavaScript外部ファイルは?というと当然できません。

WordPress子テーマには、functions.phpは継承、その他のxxxxxxx.phpは上書きして使用することができます。しかし、JavaScriptファイルは、自動で子テーマのものを呼び出してくれる仕組みはありません。

ならば、style.cssの@importように、外部JavaScriptファイル内で親テーマのJavaScriptファイルを呼び出せば、と思い以下の方法を試したのですがうまくいきませんでした。

JavaScriptファイルの中からJavaScriptを呼び出す(import)

僕はJavaScriptはかなり苦手なので、他の方法も思いつきません。

ということでしょうがないので、PHPで「子テーマフォルダ内にJavaScriptファイルが存在しているか?」「存在していたら、JavaScriptファイルを呼び出す」という機能を作ってみたので紹介です。

functions.phpの編集

子テーマ内にJavaScriptファイルが存在するかを調べるには、まず以下を調べる必要があります。

  • そもそも子テーマが使用されているのか?親テーマだけが使われている場合は存在しない。
  • 子テーマのJavaScriptファイルの存在をfile_existsで調べるにはJavaScriptファイルのローカルパスが必要

で、上記の項目を含めて、子テーマ内のファイルの存在を調べることができる関数を作ってみました。それが以下。functions.phpに書き込みます。

//子テーマ内に指定のファイルがあるかどうか調べる
//ファイルがあった場合は子テーマ内ファイルのローカルパスを(true)
//ファイルが存在しなかった場合はfalseを返す
function file_exists_in_child_theme($filename){
  $dir = str_replace('\\','/', dirname(__FILE__));//置換しているのはWindows環境対策
  $theme_dir_uri = get_template_directory_uri();//親テーマのディレクトリURIを取得
  $child_theme_dir_uri = get_stylesheet_directory_uri();//子テーマのディレクトリURIの取得
  if ($theme_dir_uri == $child_theme_dir_uri) return;//同一の場合は子テーマが存在しないのでfalseを返す
  preg_match('/[^\/]+$/i', $theme_dir_uri, $m);//親テーマのディレクトリ名のみ取得
  $theme_dir_name = $m[0];
  preg_match('/[^\/]+$/i', $child_theme_dir_uri, $m);//子テーマのディレクトリ名のみ取得
  $child_theme_dir_name = $m[0];
  $path = preg_replace('/'.$theme_dir_name.'$/i', $child_theme_dir_name, $dir, 1);//文末のディレクトリ名だけ置換
  $path = $path.'/'.$filename;//ローカルパスの作成
  if ( file_exists($path) ) {
    return $path;//ファイルが存在していたらファイルのローカルパスを返す
  }
}

関数で何をやっているかっていうと、まず以下の部分で、現在使用しているテーマのローカルパスを取得しています。置換しているのは、Windows環境対策です。

$dir = str_replace('\\','/', dirname(__FILE__));//置換しているのはWindows環境対策

上がテーマのfunctions.phpで呼び出すと、こんなローカルディレクトリパスが返されます。(Windowsで試しているので、Windowsでのローカルパスが返されています)

C:/InstantWP_4.3.1/iwpserver/htdocs/wordpress/wp-content/themes/simplicity

次に以下では、get_template_directory_uri()で親テーマのディレクトリのURI、get_stylesheet_directory_uri()で子テーマディレクトリのURIを取得しています。これらが同じならば、子テーマが使用されていないので偽(null)を返します。

$theme_dir_uri = get_template_directory_uri();//親テーマのディレクトリURIを取得
$child_theme_dir_uri = get_stylesheet_directory_uri();//子テーマのディレクトリURIの取得
if ($theme_dir_uri == $child_theme_dir_uri) return;//同一の場合は子テーマが存在しないのでfalseを返す

次の部分では、親テーマと、子テーマのディレクトリー名だけ(フルパスではない)を取得しています。

preg_match('/[^\/]+$/i', $theme_dir_uri, $m);//親テーマのディレクトリ名のみ取得
$theme_dir_name = $m[0];
preg_match('/[^\/]+$/i', $child_theme_dir_uri, $m);//子テーマのディレクトリ名のみ取得
$child_theme_dir_name = $m[0];
$path = preg_replace('/'.$theme_dir_name.'$/i', $child_theme_dir_name, $dir, 1);//文末のディレクトリ名だけ置換

親テーマディレクトリURIの赤字部分のみを取得しています。get_template_directory_uri()で取得したもの。

http://127.0.0.1:4001/wordpress/wp-content/themes/simplicity

子テーマの場合。get_stylesheet_directory_uri()で取得したもの。

Index of /wordpress/wp-content/themes/simplicity-child

で、親テーマのローカルパスの赤字部分を

C:/InstantWP_4.3.1/iwpserver/htdocs/wordpress/wp-content/themes/simplicity

次のように置換します。

C:/InstantWP_4.3.1/iwpserver/htdocs/wordpress/wp-content/themes/simplicity-child

あとは、このパスにファイル名をつけて、file_existsでファイルの存在を確認して、ファイルが存在していれば、ファイルパスを返すようにしています。

$path = $path.'/'.$filename;//ローカルパスの作成
if ( file_exists($path) ) {
  return $path;//ファイルが存在していたらファイルのローカルパスを返す
}

C:/InstantWP_4.3.1/iwpserver/htdocs/wordpress/wp-content/themes/simplicity-child/javascript.js

これで、子テーマディレクトリ内のファイルの存在を調べられるようになりました。

テンプレートファイルの編集

あとは、header.php内の<head></head>内などで、以下のように呼び出せばOKです。

<?php //子テーマディレクトリ内のjavascript.jsファイルの存在を確認。あれば呼び出す
if (file_exists_in_child_theme('javascript.js')): 。?>
  <script type="text/javascript" src="<?php echo get_stylesheet_directory_uri(); ?>/javascript.js"></script>
<?php endif; ?>

まとめ

もしかしたら、JavaScriptもしくはjQueryだけで、もっとスマートな呼び出し方法が有るのかもしれません。

ただ、現時点では、このような方法しか思いつかなかったので、備忘録がてら残しておきます。