WordPressテーマといえども、PHPを書く以上はオブジェクト指向な実装がしたいものですよね。
前の記事で紹介した通り、私の functions.php は、以下の3行だけです。
1 2 3 |
require_once( TEMPLATEPATH . '/includes/class-mytheme.php' ); $MT = new Mytheme(); $MT->init(); |
コアクラスである Mytheme の init() メソッドでは、まず、オブジェクト志向の恩恵を受けるため、オートローディングの設定を行なっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
class Mytheme { //略 public function init() { //略 //クラスファイルのAutoLoad spl_autoload_register( array( $this, 'autoload' ) ); //略 } /** * オートロード(spl_autoload_registerのコールバック) */ public function autoload( $class ) { $directories = array( TEMPLATEPATH . self::INCLUDE_PATH, TEMPLATEPATH . self::INCLUDE_PATH . 'controller/', TEMPLATEPATH . self::INCLUDE_PATH . 'admin/', TEMPLATEPATH . self::INCLUDE_PATH . 'module/', TEMPLATEPATH . self::INCLUDE_PATH . 'hooks/', ); foreach ( $directories as $dir ) { $class_path = $dir . $this->get_classfile_name( $class ); if ( is_file( $class_path ) ) { require( $class_path ); return; } } } /** * クラス名からクラスファイル名を取得 */ private function get_classfile_name( $class ) { $classfile_name = self::CLASS_FILE_PREFIX . strtolower( str_replace( '_', '-', $class ) ) . '.php'; return $classfile_name; } //略 } |
これで、includes 内で定義したクラスは、いちいち require_once しなくても使える用になります。
そして、ついつい functions.php に羅列することの多いWordPressのフック登録処理は、hooks 配下のクラスファイルに、カテゴリごとに分けて記述します。
例えば以下のようなものです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
/** * HEAD内の出力関連のフック用クラス * * @category includes / hooks * @package mytheme * @author AD5 */ class MT_Head { public function init() { add_action( 'init', array( $this, 'initialize' ) ); add_action( 'wp_enqueue_scripts', array( $this, 'styles_and_scripts' ) ); add_filter( 'pre_get_document_title', array( $this, 'document_title' ) ); //略 } /** * ACTION HOOK : init * head内のゴミ削除 */ public function initialize() { remove_action( 'wp_head', 'wp_generator' ); remove_action( 'wp_head', 'rsd_link' ); remove_action( 'wp_head', 'wlwmanifest_link' ); remove_action( 'wp_head', 'print_emoji_detection_script', 7 ); remove_action( 'admin_print_scripts', 'print_emoji_detection_script' ); remove_action( 'wp_print_styles', 'print_emoji_styles' ); remove_action( 'admin_print_styles', 'print_emoji_styles' ); remove_filter( 'the_content_feed', 'wp_staticize_emoji' ); remove_filter( 'comment_text_rss', 'wp_staticize_emoji' ); remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' ); } /** * ACTION HOOK : wp_enqueue_scripts * CSS・JSの読み込み */ public function styles_and_scripts() { wp_enqueue_style( 'style', get_stylesheet_uri() ); wp_enqueue_style( 'font-awesome', get_template_directory_uri() . '/lib/css/font-awesome.css' ); wp_enqueue_script( 'jquery' ); } /** * FILTER HOOK : pre_get_document_title * タイトルタグの設定 */ public function document_title( $title ) { global $MT; return $MT->Meta->get_document_title(); } //略 } |
ほかにも、投稿タイプやタクソノミー、リライトルールなどに関するフックを登録する MT_Setting クラス、
pre_get_posts などクエリ関連のフックを登録する MT_Query クラス、
テーマアクティベーション時の処理を登録する MT_Activate クラス、
管理画面関連のフックを登録する MT_Admin クラス、
AJAX関連のフックを登録する MT_Ajax クラス、
Cron関連のフックを登録する MT_Cron クラスなど、
フックの種類ごとにクラスを分けています。
これを実行するのは、コアクラスの、bind_hook() メソッドです。init() メソッド内でコールされています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
class Mytheme { //略 /** * 初期化 */ public function init() { //略 //各種フックの登録 $this->bind_hook( self::HOOK_CLASSES ); //略 } //略 /** * フック用クラスの初期化 */ public function bind_hook( $hooks ) { foreach ( $hooks as $hook ) { $class = self::PACKAGE_PREFIX . $hook; if ( class_exists( $class ) ) { $instance = new $class(); if ( method_exists( $instance, 'init' ) ) { $instance->init(); } } } } |
hooks ディレクトリ内にあるクラスを順次インスタンス化して、それぞれの init() メソッドを実行しています。
このような構成にすることで、たくさんのフックを登録するテーマでも、管理、追跡がしやすくなります。
今回の例では、WordPressの管理画面内にテーマ設定メニューとデータ管理メニューを追加し、それぞれに複数のサブメニューを用意しています。
WordPressの管理画面内にページを作成する際には、メニューの追加やページの表示、オプションの登録など、共通する処理が多いので、それをメニュー単位で「プロセッサ」と呼んでいるクラスにまとめています。
例えば以下のようなものです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
/** * 管理画面のサイト設定機能プロセス * * @category includes / admin * @package mytheme * @author AD5 */ class MT_Admin_Processor_Setting { public function get_config() { return array( 'title' => 'テーマ設定', 'type' => 'manage_options', 'position' => 21, 'pages' => array( 'main' => array( 'title' => '文言設定', 'options' => array( 'mt_home_main_message', 'mt_single_report_download_notice', ) ), 'mail' => array( 'title' => 'メール設定', 'options' => array( 'mt_mail_inquiry_notification_from', 'mt_mail_inquiry_notification_fromname', 'mt_mail_inquiry_notification_to', 'mt_mail_inquiry_notification_subject', 'mt_mail_inquiry_notification_content', ) ), ) ); } function main_view() { include( TEMPLATEPATH . '/admin/setting-main.php' ); } function mail_view() { include( TEMPLATEPATH . '/admin/setting-mail.php' ); } } |
get_config() メソッドが返す配列に従って、コアクラスの admin_process() メソッドが、メニューの追加処理、ページの表示処理、オプションの登録処理などを自動的に行っています。
module フォルダ内のクラスは、複数のコントローラで共通して行う処理をまとめたユーティリティ的なクラスや、テンプレートで使用する静的メソッドを集めたクラスが入っています。