WordPressのマルチサイト案件で、子テーマを使って効率よくカスタマイズする。

この間、WordPressのマルチサイトモードで、8サイトくらいあるサイトを作りました。

一つのサイトですが、更新コンテンツがとにかく大量にあっりました。
そのコンテンツがカスタムフィールドばりばり使ったり、デザインがいろいろ違っていたり、求められる機能がいろいろ違ったりしていて、カスタム投稿やタクソノミーでは、開発しづらいし運用も大変だろうな・・・・ということで、マルチサイトで子テーマを6つくらい作りました。そのときのやったこと、やれば良かったことなどなど。

そもそも子テーマとは

子テーマ – WordPress Codex 日本語版

要は、あるテーマを元にしてそのテーマを一部だけ改変したようなテーマを作成できる機能です。ただ、読み込み順は子テーマ→親テーマとなるので、子テーマに足りないものを親テーマから保管する機能と言ったほうが正確かも知れません。
継承って言い方をしていますが、プログラミングにおけるクラスの継承とは全く別物なので注意が必要です。

なので、get_header()とかを子テーマで、書いた場合、子テーマ内のheader.phpを探しにいって、なかった場合、親テーマのheader.phpが呼ばれます。
また、子テーマにarchive.php、親テーマにcategory.phpがある場合は、カテゴリーページにアクセスしたら親テーマのcategory.phpが呼ばれるようです。まぁ、そうじゃないと、index.phpを作ったら全部のテンプレートを上書きってことになってしまいますもんね。

子テーマの作成

子テーマとしてテーマを作成するためには、style.cssの最初のテーマ用コメントに Template: 親テーマのディレクトリ名とするだけです。また、子テーマの場合、index.phpが無くても大丈夫です。

また、子テーマの子テーマ、孫テーマみたいなのは作成できません。1世代までです。

子テーマ、親テーマで値が変わる関数や、定数

正直全部は説明できませんが、とりあえず、

  • bloginfo(“stylesheet_directory'”)/bloginfo(“template_directory'”)
  • get_stylesheet_directory()/get_template_directory()
  • get_stylesheet_directory_uri()/get_template_directory_uri()
  • STYLESHEETPATH/TEMPLATEPATH

の値は変わります。
stylesheet・・・シリーズは子テーマ、templateシリーズは親テーマの情報を返します。
なので、テーマ内で使う画像やCSS等、共通のリソースは親テーマに突っ込んでおく&なるべくtemplateシリーズでの記述ををお勧めします。

また、is_child_theme()という関数もあるようです。

functions.php

functions.phpだけは存在すれば読み込まれない、という挙動ではなく、子テーマのfunctions.php→親テーマのfunctions.phpの順で両方読み込まれます。カスタム投稿・タクソノミーの設定は、子テーマのfunctions.phpに記述するといいかもしれません。

また、

子テーマのfunctions.php で同名の関数があれば、子テーマの関数が使用されます。

という記述が日本語版Codexにありますが、これは、ちょっと言葉足らずで、そのまま同名の関数を書くと、「Cannot redeclare」のエラーを吐いてしまいます。なので、親テーマに再定義可能な関数を作る場合は

としてあげる必要があります。英語版のCodexにはここら辺のこともちゃんと書いてあります。Child Themes « WordPress Codex

また、テーマで使う変数も保護しないと上書きされてしまうのでここら辺は注意が必要です。変数の上書きはエラーにならないので、定数にしておく等の工夫が必要です。

テーマの構造の設計における注意

ちゃんと使いこなせば、いろいろ便利な機能ですが、ちゃんと設計しないと、「別々にテーマを作った方が、楽だった」になんてことになりかねない機能でもあります。
なので、いくつか注意事項、というより現時点で僕が気を使っているルールです。

親テーマを実際に使用するテーマにしない

一番最初にマルチサイト+子テーマでサイトを作ったときに、親テーマを親サイト(ルートサイト)に設定していたために、死ぬほど苦労した結果、子テーマをやめた。なんて失敗もありました。

親サイトはトップページなど、再利用性が低いものが入ることが多いですし、front-page.phpや、home.phpなど、テンプレートの読み込み順の優先度が高いものを使うことも多いです。これを子テーマ側でいちいち作成するのはとても面倒。無駄。これだけは絶対やってはいけないです。

また、親テーマを実際に利用していると、「このサイトではカテゴリーも月別アーカイブも全部一緒でいいのに・・・・」みたいなことが発生し易いです。
なので、親テーマに置くのは、ほんとに共通で使い回す部分だけ&テンプレートの読み込み順が低いもの例えば、

  1. header.php/footer.php等のモジュール系
  2. archive.php
  3. index.php
  4. テーマ内で使い回したい関数、ヘルパー等のライブラリ

等に留めましょう。

親テーマのfunctions.phpの肥大化を避ける

別に子テーマを使ったりしなくてもという話でもあるんですが、マルチサイトは基本的に大きな案件にならないと使わないとは思いますが、そうなってくると、どんどん全部で使い回すようなカスタマイズが、functions.phpに蓄積していきます。

ただ、管理画面のカスタマイズなど、テーマとの関連性が薄いもの、すべてのサイトで活用するものはfunctions.phpではなく、プラグインにして極力テーマの見通しを良くしましょう。カスタム投稿タイプ等は冗長になりがちなので、プラグインで関数を作るなりクラスを作り、それをテーマで使い回す等が便利だと思います。

その他やっておいた方が、いいかもと思うこと。

body_classにサイト名を出力


をプラグインとかfunctions.phpに書いておくと、site-hogeみたいなクラスを吐くので便利かもしれません。特にテーマを識別する手段が無いので。。

blog_idに依存しない

特にテーマを別環境で作っているときは気をつけたいのですが、現在のサイトを識別する手段が、グローバル変数の$blog_idくらいしか無かったと思います。ただ、テーマにIDを直書きするのはメンテナンス性を欠くので、get_id_from_blogname( “hoge” )とかで、パスで指定する方が設定とテーマの分離ができて良いのかなと思います。

前回の記事でもそんなとき使えるものを書きました。

https://torounit.com/blog/2013/04/25/1514/

WordPressのマルチサイト機能3.0からMUと統合されたまだまだ新しい機能です。対応していないプラグインもあります。僕のリリースしているCustom Post Type Permalinksもちゃんと対応できておりません(汗)
またカスタム投稿との棲み分けとかも考えないといけない部分があります。

ただ、ちゃんと使いこなせれば、更新コンテンツが多い、ユーザーが多い案件等でもかなり使い易い構築ができるんじゃないかな・・・と思っています。