WordPress 有料テーマ Snow Monkey の基本的な構造について – ディレクトリ構成編

Snow Monkey アドベントカレンダー4日目の記事です。昨日は「WordPress 有料テーマ Snow Monkey の基本的な構造について – Composer 編」として Snow Monkey と Composer について書きました。今日はディレクトリ構成がどうなっているかを書きたいと思います。

WordPress テーマのディレクトリ構成

早速ですが、ディレクトリ構成って結構悩みませんか?例えばよくあるのは画像用のディレクトリをどう配置するのかとか。あと functions.php に何でもかんでも書き込むと10,000行とかえらいことになるので当然分割すると思いますが、そういったファイル群をどう配置するのかとか。また、WordPress のテーマディレクトリって仕組み上散らかりやすいようになっているんですよね。例えば各ページごとのテンプレートとかも全部直下に置かないといけないので page-11.phppage-12.php みたいなファイルがすごい数になると同じ階層にバーっと色々な種類のファイルが混ざって把握するのが難しくなってしまいます。

どう構成するのがわかりやすいか日々悩んでいたのですが、Mimizuku、Snow Monkey と開発する中である程度自分なりの形が見えてきました。

開発中のディレクトリ構成

全部書くとかなり長くなっちゃうので一部省略していますが、おおよそ下記のような構成としています。

snow-monkey/
├ bin/                                     # 便利シェルスクリプト用ディレクトリ
│ ├ phpunit.sh                      # phpunit を実行するシェルスクリプト
│ ├ server.sh                        # ローカルサーバーを起動するシェルスクリプト
│ ├ ...
├ resources/                         # 一般的なテーマのディレクトリ直下に相当するディレクトリ
│ ├ app/                               # functions.php を分割させたファイルを配置するディレクトリ
│ ├ src/                                # css、js のソースファイル(Sass、ES6)
│ ├ templates/
│ ├ ...
│ ├ front-page.php
│ ├ functions.php
│ ├ index.php
│ ├ screenshot.png
│ └ style.css
├ tests/
├ .editorconfig                      # エディタの設定ファイル
├ .gitignore
├ README.md
├ codesniffer.ruleset.xml    # CodeSniffer の設定ファイル
├ composer.json                  # Composer の設定ファイル
├ composer.lock
├ gulpfile.js                           # Gulp の設定ファイル
├ license.txt
├ package.json                     # npm の設定ファイル
├ phpmd.ruleset.xml           # PHPMD の設定ファイル
├ phpunit.xml                       # phpunit の設定ファイル
└ yarn.lock

これは開発時のディレクトリ構成なのですが、開発時って .composer.json とか gulpfile.js とかの設定ファイルがたくさん必要じゃないですか。現代では Sass 使わないとか無いので。ただ、こういう設定ファイルは基本的にプロジェクト(今回で言えばテーマ)のルートに置くので、テーマに必要な PHP ファイルとまざって余計ごちゃごちゃうになっちゃうんですよね。

なので僕はテーマに必要なファイル群を全部 resources/ というディレクトリの中にいれています。もちろん style.css もです。実はこういう配置にしても WordPress はちゃんとテーマを認識してくれるんですよね。WordPress は style.css があるディレクトリをテーマと認識します。 /themes/snow-monkey/style.css なら、WordPress はテーマを snow-monkey と認識しますが、/themes/snow-monkey/resources/style.css と配置すれば WordPress はテーマを /snow-monkey/resources と認識します。こうすればテーマディレクトリ直下ごちゃごちゃ問題解決できて超良いですよね!素晴らしい!

ただ、1つだけ問題があるのです。これは WordPress コアのバグといっても過言ではないと思うのですが、アップデートのときにうまくディレクトリを認識してくれず、アップデートに失敗してしまうのです。本来であればテーマのワンクリックアップデートは公式ディレクトリ掲載テーマの専売特許ですが、Snow Monkey は公式ディレクトリ掲載テーマと同じようにアップデート機能を提供しているので、これが問題になってしまうんですよね…。

なので一般的な WordPress でサイト制作な仕事であれば、アップデート機能を仕込むということはあまり無いと思いますので、こういう風に一段落としてそのまま運用もするというのはなかなか良いかもしれませんね。

リリース版のディレクトリ構成

というところで、一般的なテーマのディレクトリ直下に相当する resources/ の中の構成も解説したいと思います。ですが、前述したように /snow-monkey/resources/style.css な構成のままだとアップデートが失敗するので、このままでリリース(配布)することはできません。そこで、Snow Monkey は GitHub へのプッシュ時に、連携させた Travis CI で一般的なテーマと同じ階層を持った、リリース版の Snow Monkey をつくるようにしています。そのリリース版のディレクトリ構成はこちら。

snow-monkey/
├ app/
│ ├ customizer/
│ │ ├ static-front-page.php
│ │ ├ title-tagline.php
│ │ └ ...
│ └ setup/
│     ├ assets.php
│     ├ editor-style.php
│     ├ nav-menus.php
│     └ ...
├ assets/
│ ├ css/
│ │ ├ ...
│ │ ├ object/
│ │ │ ├ component/
│ │ │ ├ _btn/_btn.php
│ │ │ ├ ...
│ │ ├ editor-style.css
│ │ ├ editor-style.min.css
│ │ ├ style.css
│ │ └ style.min.css
│ ├ js/
│ │ ├ app.js
│ │ └ app.min.js
│ └ packages/
│     ├ font-awesome/
│     ├ slick-carousel
│     ├ ...
├ languages/
├ page-templates/
│ ├ left-sidebar.php
│ ├ ...
├ src/
│ ├ css/
│ └ js/
├ template-parts/
│ ├ breadcrumbs.php
│ ├ copyright.php
│ ├ ...
├ templates/
│ ├ layout/
│ │ ├ footer/
│ │ ├ header/
│ │ ├ sidebar/
│ │ └ wrapper/
│ ├ view/
│ │ ├ 404.php
│ │ ├ archive.php
│ │ ├ content.php
│ │ ├ ...
│ └ widget/
├ vendor/
│ ├ inc2734/
│ │ ├ mimizuku-core
│ │ ├ wp-breadcrumbs/
│ │ ├ ...
│ ├ ...
├ comments.php
├ front-page.php
├ functions.php
├ index.php
├ screenshot.png
└ style.css

書き出すとめっちゃ長い…。

/app/

/app/ の中には functions.php に書くようなコードを、機能・役割ごとに分割して配置しています。さらに、Snow Monkey はカスタマイザーが多機能なので、カスタマイザー系のコードを /app/customizer/ にまとめ、それ以外を /app/setup/ の中にまとめるようにしています。

/app/ の中には、Snow Monkey の動作を定義する非常に重要なファイルが配置されています。余程のことがない限り、子テーマで /app/ 内のファイルを上書きすることは推奨できません。もし独自のウィジェットエリアを追加するなど、Snow Monkey の機能を拡張したい場合は子テーマの functions.php などに追記することを推奨します。

/assets/

実際に読み込まれる CSS や JS 用のディレクトリです。ちょっと特徴的なのは、/assets/css/object/component/_btn/_btn.php のように PHP ファイルも配置していることです。「assets なのに PHP とはどういうこと?」と思われる方もいらっしゃるかもしれません。これはカスタマイザーが出力するスタイルを定義したファイルになります。例えば Snow Monkey はカスタマイザーでメインカラーの設定ができるようになっているのですが、メインカラーは色々な箇所で利用されます。例えばリンク色とか、見出しの装飾の色とか。それらは最初は /app/setup/ の中に書いてたりしていたのですが、CSS もきちんとコンポーネント毎に整理して書いているのだから、それにあわせてカスタマイザーが出力するスタイルを定義したファイルも配置したほうがわかりやすいんじゃない?ということでこのような配置にしました。

あとは/assets/packages/ ですね。ここには本来 npm でインストールして /node_modules/ に配置されるファイルを配置しています。なんか /node_modules/ を直接参照するのがどうなのかなぁというのがあって。

/template-parts/

このディレクトリにはページネーションとかロゴとか記事一覧とかのコンポーネントを切り出して入れています。別に普通にページテンプレートに書けばよくね?という方もいらっしゃると思いますが、切り出しておくことで使いまわしもしやすくなりますし(get_template_part() で簡単に呼び出せる)、子テーマで「この部分だけ上書きしたい」というときに上書きする対象を最小限に抑えられるというメリットもあります。もしページテンプレートに直接記述している場合は子テーマでページテンプレートをまるごと上書きするしか方法がなく、上書きの影響範囲がものすごく大きくなってしまいます。そうすると親テーマがアップデートして HTML 構造が変わったりしたときにもろに影響を受けてしまうことがあるので、なるべく細かく切り出したほうが良いと僕は考えています。

/templates/

特徴的なのはこのディレクトリですね。

/templates/layout/、/templates/view/

このディレクトリ内にはさらに「header」「footer」「sidebar」「wrapper」というディレクトリがあります。WordPress は page.php や single.php のようなテンプレートがそのページ全体のビューとなるような仕組みになっています。ですがそれだと、header.php や footer.php で共通部分を切り出しているとはいえ、どうしても重複する部分がでたり、レイアウトの切り替えをしようとすると煩雑になったりしてしまいます。そこで Snow Monkey ではpage.php や single.php をビューコントローラーとして使用し、レイアウトファイルとビューファイルを指定してページをレンダリングする、という方法をとっています。そして、レイアウトファイルを /templates/layout/wrapper/、ビューファイルを /templates/view/ の中に配置するようにしています。

ヘッダーやフッターのバリエーションも本来であれば header-xxx.php とか header-yyy.php のような名前でテーマディレクトリ直下にざーっと配置しなければいけないのですが、Snow Monkey ではファイルが散らばらないように /templates/layout/header/ や /templates/layout/footer/ の中にバリエーションを配置して切り替えられるようにしています。

/templates/widget/

Snow Monkye では様々なオリジナルウィジェットを用意していますが、そのウィジェットのビュー(実際に画面に表示される HTML)を /templates/widget/ の中にファイルを置くことで上書きできるようにしています。

/

テーマディレクトリ直下も特徴的です。↑のほうに書いたディレクトリツリーで、ディレクトリ直下の PHP ファイルは省略せずに書いています。と考えると、存在するファイルは

├ comments.php
├ front-page.php
├ functions.php
├ index.php

だけしかありません。header.php や footer.phphome.php などはどこにあるのでしょうか?通常、WordPress は「子テーマ → 親テーマ」という順にテンプレートを読み込んで、子テーマにあれば個テーマのテンプレートを、親テーマにあれば親テーマのテンプレートを利用する、という仕組みになっていますが、Snow Monkey はもう1工夫して「子テーマ → 親テーマ → mimizuku-core(composer のライブラリ)」という順にテンプレートを読むようになっているのです。これもテーマディレクトリ直下をきれいに保つための仕組みです。mimizuku-core に入っているテンプレートはすごくシンプルなものなので、もし上書きしたいという場合があれば、それだけテーマディレクトリ直下にファイルを置いて上書きすれば良い、というわけです。

最後に

Snow Monkey ではいかにテーマディレクトリ直下が散らからないようにするか、そして、機能や役割ごとにファイルを正しく分割・配置して、あの機能についてのファイルならここにあるだろうなということが直感的にわかるようにする、というところに力を入れてディレクトリ構成を設計しました。意外にあまりスタンダードが無い部分だと思うので、よろしければみなさんがどうしてるかもきかせてもらえると嬉しいです!

明日は

明日は福岡のさとうさんが参加してくれています!なんと12/12、12/20も登録してありますね。3記事!ご無理なさらずに…笑

この記事を書いた人

キタジマ タカシ

長崎県長崎市在住。地元のWeb制作会社でWebデザイナー/エンジニアとして従事した後、2015年にフリーランス [ モンキーレンチ ] として独立。WordPress のテーマやプラグイン、ライブラリ、CSS フレームワーク等、多数のプロダクトをオープンソースで開発・公開しています。

Snow Monkey オンラインコミュニティ

Snow Monkey をより良いテーマにするために、今後の機能開発等について情報共有したりディスカッションをしたりする場所です。より多くのユーザーの交流があったほうがより良いプロダクトに育っていくと思いますので、ぜひご参加ください!