テーマ内のファイルを静的サイトのように階層分けする方法(WordPress)

#はじめに
- 記事の投稿をしたいのでWordPressを使って欲しい
- 固定ページがたくさんある
- 静的サイトのようにディレクトリを分けてファイル（画像とかも）を管理して欲しい（テーマ内で）

このような要望・条件での開発を行った時に少しはまったのでメモとして残しておきます。


#はまったこと
テーマ内にフォルダを作ってファイルを階層分けした時に、管理画面において固定ページのテンプレートが表示されない（故に設定できない）


#解決方法
```php:/wp-includes/class-wp-theme.php
// $files = (array) $this->get_files( 'php', 1 ); // 修正前 
$files = (array) $this->get_files( 'php', -1 ); // 修正後
```
**最後に注意書きあり**

#前提
一般ユーザー用のページとログイン後の会員ユーザー用のページがあるサイトを作る前提で話を進めます。

**＜一般ユーザー用のページのURL例＞**
example.com/ -> トップページ
example.com/about/ -> 会社概要ページ
example.com/contact/ -> お問い合わせページ

**＜会員ユーザー用のページのURL例＞**
example.com/member/ -> 会員トップページ
example.com/member/page-a -> Aページ
example.com/member/page-b -> Bページ

このように会員ユーザー用のページはパーマリンクに/member/をはさむような設定にするとします。
また、各固定ページにカスタムテンプレートを用意するとします。

#普通に作ると

テーマディレクトリ/
　　　　├ index.php（一般トップ）
　　　　├ about.php（会社概要用カスタムテンプレート）
　　　　├ contact.php（お問い合わせ用カスタムテンプレート）
　　　　├ member.php（会員トップ用カスタムテンプレート）
　　　　├ page-a.php（Aページ用カスタムテンプレート）
　　　　├ page-b.php（Bページ用カスタムテンプレート）

こんなようにテーマディレクトリ直下に全てが置かれるかと思います。


#今回作りたい構造
テーマディレクトリ/
　　　　├ index.php（一般トップ）
　　　　├ about.php（会社概要用カスタムテンプレート）
　　　　├ contact.php（お問い合わせ用カスタムテンプレート）
　　　　└ member/
　　　　　　　├　member.php（会員トップ用カスタムテンプレート）
　　　　　　　├　page-a/
　　　　　　　│　　└　page-a.php（Aページ用カスタムテンプレート）/
　　　　　　　└　page-b/
　　　　　　　　　　└　page-b.php（Bページ用カスタムテンプレート）/

#はまったところ
管理画面にて固定ページのテンプレートを設定しようとした時に、3階層以上深いところにあるファイルが表示されませんでした。（今回でいうとpage-a.phpやpage-b.php）
![スクリーンショット 2017-12-23 23.38.23.png](https://qiita-image-store.s3.amazonaws.com/0/112614/cd00fe80-4eb5-3002-2781-223d557d867f.png)

そこで原因を色々調査してみました。

#調査内容
まず、このテンプレートの一覧はどうやって生成しているのかを確認しました。
`<select name="page_template" id="page_template">`
このようなソースだったので`id="page_template"`でWordPress内のファイルを検索しました。
すると、`/wp-admin/includes/meta-boxes.php`がヒットしました。
どうやらそのファイルの中の`<?php page_template_dropdown( $template, $post->post_type ); ?>`がoptionを生成しているみたいです。

なので次に`page_template_dropdown`で検索します。
すると`/wp-admin/includes/template.php`がヒットしました。
foreachで回してoptionを生成してることがわかりました。で、その元ネタはというとおそらく少し上の`get_page_templates（null, $post_type);`で取ってきてるんだろうなと予測を立てました。

なので次は`get_page_templates`で検索します。
`/wp-admin/includes/theme.php`と`/wp-includes/class-wp-theme.php`がヒット。
どうも前者の中で後者を呼んでるっぽいです。後者の中ではさらに`get_post_templates`を呼んでる。
なので`get_post_templates`で検索しました。
すると`/wp-includes/class-wp-theme.php`がヒットしました。

`/wp-includes/class-wp-theme.php`の中で`php`がつくファイルをどこかから取ってきてその中の"Template Name"っていう文字列を検索してきてごにょごにょしてるみたいです。
Template Nameってのはカスタムテンプレートの上部に書くものですね。どうやらここが第三階層のファイルまで見にいってくれてないのが直接的な原因のようです。
`$files = (array) $this->get_files( 'php', 1 );`　ここの処理が怪しそうなので`get_files`で検索すると同じファイル内に定義がありました。
関数の説明部分にこんな記載がありましたが、まさにここが原因のようです。

```
* @param int $depth Optional. How deep to search for files. Defaults to a flat scan (0 depth). -1 depth is infinite.

```

get_filesの引数を-1にすればテーマ内のファイルを無限に再帰的に読みに行ってくれるようなので、先ほどの`/wp-includes/class-wp-theme.php`内の`$files = (array) $this->get_files( 'php', 1 );`を`$files = (array) $this->get_files( 'php', -1 );`にしてみました。

すると


![スクリーンショット 2017-12-24 0.05.02.png](https://qiita-image-store.s3.amazonaws.com/0/112614/58b5f27e-8a3a-9554-9b25-fa07ba5b571e.png)

ちゃんと出力されました！

#余談
固定ページの設定内容はどこに保存されてるかMySQLの中身を見てみました。

wp_postmetaテーブルのmeta_keyが_wp_page_templateのmeta_valueに格納されているようです。

![スクリーンショット 2017-12-24 0.12.12.png](https://qiita-image-store.s3.amazonaws.com/0/112614/d62f0700-a22f-e84a-1b35-30e85693f39c.png)






#注意点
- 基幹ファイルをいじってるので、WordPressの更新時に上書きされてしまうと思います。（function.phpにフィルターフックを書けばOKか？）
- こんなことやらなくてもやりたいことは実現できるのかもしれません。
- そもそもこんなことやるんだったらWordPressは使うなという話でしょうか。