はじめに
- 記事の投稿をしたいのでWordPressを使って欲しい
- 固定ページがたくさんある
- 静的サイトのようにディレクトリを分けてファイル(画像とかも)を管理して欲しい(テーマ内で)
このような要望・条件での開発を行った時に少しはまったのでメモとして残しておきます。
はまったこと
テーマ内にフォルダを作ってファイルを階層分けした時に、管理画面において固定ページのテンプレートが表示されない(故に設定できない)
解決方法
// $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)
そこで原因を色々調査してみました。
調査内容
まず、このテンプレートの一覧はどうやって生成しているのかを確認しました。
<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 );
にしてみました。
すると
ちゃんと出力されました!
余談
固定ページの設定内容はどこに保存されてるかMySQLの中身を見てみました。
wp_postmetaテーブルのmeta_keyが_wp_page_templateのmeta_valueに格納されているようです。
注意点
- 基幹ファイルをいじってるので、WordPressの更新時に上書きされてしまうと思います。(function.phpにフィルターフックを書けばOKか?)
- こんなことやらなくてもやりたいことは実現できるのかもしれません。
- そもそもこんなことやるんだったらWordPressは使うなという話でしょうか。