TECHBLOG

WordPress > MVC構築

WordPressをMVCで構築

Create:

Update:

Category:WordPressMVC構築

[ Version.19 ]

概要

WordPressは、Symfony系と異なり、php が書ければ(極論ほとんど書けなくても)誰でも実装できる手軽さがありますが、反面、複雑なシステムを組む場合はコードの見通しがとても悪くなります。

弊社では、WordPressもMVCモデルで構築することで、複雑な仕様でも見通しのよいコードに仕上げています。

構築コンセプトは「メンテナンスに強い」です。

MVCとは

そもそもMVCとは、「Model(モデル)」「View(ビュー)」「Controller(コントローラ)」の三つの役割に分離して実装し、それらが連携して処理を進める方式。

語弊をおそれずに以下それぞれ。

Model

DBから値(各フィールドの値)を取得してControllerで使いやすくなるよう事前準備。

Controller

DBから指定行(レコード)をとってきて、Viewに渡す。

View

Controller から受け取った値を表示する。

※ WordPressではテーマファイル群がこれにあたります。

※ Symfony系なら入力欄などから Controller 経由でDB操作しますが、WordPressではほとんどありません。

Model&Controller

具他的には下記のようなコードを記述します。

Modelサンプル(XxModel.php)

/**--------------------------------------------------------------
 *
 * XxModel
 *
 --------------------------------------------------------------*/
class XxModel extends OoAttr
{
	public function getAttr($post_id)
	{
		/* post */
		$post = (object) [];
		$post->post_id = $post_id;
		$post->post_title = get_the_title($post_id);
		$post->permalink = get_permalink($post_id);
		// dete
		$post->post_date = get_the_date('Y/n/j(D)', $post_id);
		// content
		$post->post_content = parent::post_content($post_id);
		// acf
		$post->acf_texts = $this->acf('acf_texts', $post_id)->textarea()->get();
		$post->acf_pic = $this->acf('acf_pic', $post_id)->image('medium')->get();
		$post->acf_radio = $this->acf('acf_radio', $post_id)->radio('both')->get();
		$post->acf_group = (object) [];
		$post->acf_group->texts = $this->acf('acf_group', $post_id)->group('texts')->textarea()->get();
		return $post;
	}
}

上記は、OoAttrを継承しているのですが、詳細は割愛し先ずは全体像を。

投稿タイプ一つに対して、1モデル作成し、必要な値をオブジェクトで取得できるようにしています。

acf() はカスタムフィールドのセッターで、途中処理して、 get() で取得しています。

命名は絶対遵守で、アッパーキャメル「投稿タイプ名Model 」にしています。

Laravel の Controller eloquent のような記述法です。

Controllerサンプル(xx_archive_controller.php)

これは、カスタム投稿タイプアーカイブテンプレートのControllerサンプルです。

/**--------------------------------------------------------------
 *
 * xx_archive_controller
 *
 * @model	XxModel
 *
 --------------------------------------------------------------*/
/* setting */
// $the_posts_per_page = 20;
/* model */
include_once TEMPLATEPATH . '/model/XxModel.php';
$XxModel = new XxModel();
/* archive */
$arr = [];
$args = [
	'post_type'      => 'xx',
	'posts_per_page' => $the_posts_per_page
];
$the_query = new WP_Query( $args );
if ($the_query->have_posts()) {
	while ($the_query->have_posts()) {
		$the_query->the_post();
		$arr[] = $XxModel->getAttr($the_query->post->ID);
	}
}
$wp_archive_posts = $arr;
/* title */
$archive_name = 'xx一覧';
$archive_name .= is_paged() ? ' [ ' . get_query_var('paged') . '/' . $the_query->max_num_pages . ' ]' : '';
if (is_year()) {
	$wp_archive_title = get_query_var('year') . '年の' . $archive_name;
} elseif (is_tax()) {
	$temp_term = get_term_by('id', $query_term['term_id'], $XxModel::the_taxonomy);
	$wp_archive_title = $temp_term->name . 'の' . $archive_name;
} else {
	$wp_archive_title = '' . $archive_name;
}

Controller は、各テンプレート(View)に対して、1ファイル用意するようにしています。

命名規則は絶対で、投稿タイプ名_テンプレート種_controller.php としています。

get_posts(関数)などは使用せず、サイト内共通でWP_Query(class)を使用します。

特にqueryを操作する必要がない場合は、$the_query = $wp_query; のように記載します。

Viewサンプル(archive-xx.php)

WordPressのアーカイブテンプレートのサンプルです。

どのページにも共通で命名規則に則ったファイルを読み込みます。

テンプレートの記述は、php、blade、twig で可能な限り統一しマークアップエンジニア間のコードのnバラつきを減らしています。

<?php
/*--------------------------------------------------------------------------
	archive-xx
---------------------------------------------------------------------------*/
/* base */
$PAGENAME = '*';
$DIRNAME = 'ディレクトリ';
define('DIRCODE', 'xx');
define('PAGECODE', 'archive');
/* contoroller */
include_once TEMPLATEPATH . '/controller/' . DIRCODE . '_' . PAGECODE . '_controller.php';
/* head & header */
include_once TEMPLATEPATH . '/header.php';
/*---------------------------------------------------------------------------*/
?>
<div class="title_wrap">
	<div class="title">
		<h1 class="title_text"><?= $wp_archive_title?></h1>
		<p class="title_text_sub">DIR</p>
	</div>
</div>
<div class="contents_wrap">
	<div class="<?= DIRCODE ?>_<?= PAGECODE ?>_contents contents">
		<section class="area">
			<div class="hgroup">
				<h2 class="heading02"><?= $wp_archive_title ?></h2>
			</div>
			<div class="box">
				<div class="part">
					<div class="cont texts">
<?php	foreach($wp_archive_posts as $post) : ?>
<?php		if($post->acf_radio === 'aaa') :  ?>
						<p><a href="<?= $post->permalink ?>"><?= $post->post_title ?>(<?= $post->post_date ?>)</a></p>
<?php		endif; ?>
<?php	endforeach; ?>
					</div>
				</div>
			</div>
		</section>
	</div>
</div>
<?php	include_once TEMPLATEPATH . '/footer.php'; ?>

本サンプルについて

「テンプレートファイルに全て書ききってしまえばいいのに・・」と思われるかもしれません。

しかし、システムが複雑な場合でも簡単な場合でも同じ記述をすることで、コーディングとシステムにおいてスタッフ間の役割分担が明確になり、管理もしやくなっています(=メンテナンスに強いサイト)。

loading