動機
WordPressの特性上、ビルドイン関数で簡単に操作できるとはいえ、一つのファイルに全て詰め込んでしまうのもいかがなものかと感じたのがきっかけです。
テンプレートファイルを触っている時に、いつの間にか機能改善や追加などで膨れ上がっていることがあります。修正するのも一苦労で、どこにどういった処理が書かれているのかわからなくなることもあります。
そのようなことにならないよう、責務をしっかり分けたディレクトリ構成にしたいのが目標です。
なぜMVCモデルなのか
アーキテクチャとして理解しやすかったからです。
それぞれ役割を分けファイル分割することでコードの見通しと責任が明確になります。
Viewについては、WordPressテンプレートファイルとみなします
-
Model
DB操作、ビジネスロジックを担う -
Controller
Viewへのデータ引き渡し、Modelへのデータ処理指示を担う -
View
ユーザーインターフェイス側(表示させる画面)を担う
ディレクトリ構成
Viewについては各テンプレートファイルとみなします。
.
└── sample-theme/
├── front-page.php
└── includes/
├── models/
│ └── Post.php
└── controllers/
└── FrontPageController.php
Model
ここでは取得したい投稿やページなど引数で指定し、得たデータを返す関数を設定しています。モデルの責務らしく、データベースへの問い合わせ場所になっています。
<?php
class Post
{
public function getPosts(array $args = []): array
{
global $post;
$posts = [];
$postQuery = new WP_Query($args);
if ($postQuery->have_posts()) {
while ($postQuery->have_posts()) {
$postQuery->the_post();
$posts[] = $post;
}
wp_reset_postdata();
}
return $posts;
}
}
Controller
Viewへ渡すデータを用意しています。
今回の例では記述量が少ないですが、必要なデータが増えるほどモデルとのやり取りが増え、処理の複雑さも増してくることが予測されます。
最もここではなるべくロジックは書かないようにしたいので、ページ特有処理がある場合はユースケースなどを作成し、そちらに委譲するのも一つの手かと考えます。
<?php
require_once __DIR__ . '/../models/Post.php';
$postModel = new Post();
$posts = $postModel->getPosts([
'post_type' => 'post',
]);
View
Controllerから得たデータを表示させています。
<?php
require_once __DIR__ . '/includes/controllers/FrontPageController.php';
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
<?php foreach ($posts as $post) : ?>
<li><?= $post->post_title; ?></li>
<?php endforeach; ?>
</ul>
</body>
</html>
注意点
先述したControllerについて、処理の複雑さはFatなControllerを招きます。これらの対策として、ユースケースもしくはモデルに処理を委譲できないか見直していくことが必要です。
さいごに
GoQSystemでは一緒に働いてくれる仲間を募集中です!
ご興味がある方は以下リンクよりご確認ください。