WordPressのテーマ開発でMVCモデルを実現する。
これはある種のチャレンジです。
もっとも、モデルの役割は WP_Query クラスなどの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 46 47 48 49 50 51 52 53 |
class Mytheme { //略 public function init() { //略 //コントローラーのルーティング $this->route_controller(); //略 } //略 public function route_controller() { add_action( 'template_include', array( $this, 'apply_controller' ), 9999 ); } public function apply_controller( $template ) { $class = self::PACKAGE_PREFIX . strtr( ucwords( strtr( basename( $template, '.php' ), array( '-' => ' ' ) ) ), array( ' ' => '_' ) ) . self::CONTROLLER_SUFFIX; if ( class_exists( $class ) ) { $controller = new $class(); global $post; if ( ! empty( $post->post_name ) && method_exists( $controller, $post->post_name . '_action' ) ) { $action = $post->post_name . '_action'; } else { $action = 'index_action'; } if ( method_exists( $controller, 'init' ) ) { $controller->init(); } $return = $controller->$action(); if ( $return ) { foreach ( $return as $key => $value ) { $this->properties[$key] = $value; } } } return $template; } public function get( $key ) { if ( array_key_exists( $key, $this->properties ) ) { return $this->properties[$key]; } else { return false; } } } |
ここでは、WordPressのテンプレート決定ロジックに対応した、自動ルーティングを実装しています。
例えば、page-mypage.php がテンプレートとして表示される場合には、自動的に MT_Page_Mypage_Controller が、single-ebook.php が使用される場合には、MT_Single_Ebook_Controller がインスタンス化され、xxx_action() メソッドが実行されます。
実行されるアクションメソッドは、表示しようとしている投稿のスラッグによって決定され、該当するものがなければ、index_action() となります。
コントローラクラスは、例えば以下のような内容です。
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 58 59 60 61 62 63 |
<?php /** * マイページ処理クラス * * @category includes / controller * @package mytheme * @author AD5 */ class MT_Page_Mypage_Controller { private $auth; public function init() { //ログイン認証 $this->auth = new MT_Auth(); if ( ! $this->auth->is_author_signed_in() ) { wp_safe_redirect( MT_Utility::get_pagelink( MT_Const::PAGE_SIGNIN ) ); } } /** * ACTION * マイページトップ(投稿一覧) */ public function index_action() { $args['post_type'] = 'ebook'; $args['post_status'] = array( 'publish', 'pending', 'draft', 'trash' ); $args['author'] = $this->auth->get_userid(); $args['posts_per_page'] = 20; $args['paged'] = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;; $query = new WP_Query( $args ); return array( 'view' => 'index', 'query' => $query ); } /** * ACTION * レポート新規投稿 */ public function add_action() { if( ! empty( $_POST ) ) { //略 } return array( 'view' => 'add', 'form' => $form, 'categories' => $categories, 'tags' => $tags ); } //略 } |
各アクションメソッドは、戻り値として、テンプレートで使用するデータの配列を返します。
これを、コアクラスが受け取り、properties プロパティに格納します。
そして、テンプレートで以下のように値を受け取ります。
1 |
$MT->get('profile'); |
こうすることで、テンプレートファイルにダラダラと書きがちなロジックを、コントローラクラスに分離することができました。