はじめに
初めまして。フリーランスのテクニカルディレクターをしております。Daiskyと申します。ジーズアカデミーアドベントカレンダー13日目に投稿する予定だったWordPressについて書こうと思います。
G'sではWordPressが話題に上がる事は殆どないので逆に面白いかなと思うのと、初めてWordPressについて勉強した時に、情報が全体的に冗長だなと感じたので
- 要所だけをかいつまんで
- サクッと入門できる
- ハンズオン形式
でWordPressの説明をできればと思います。
一般的なIT用語とMVCフレームワークの話をちょっとしているので全くの初心者の方には向かないと思いますが、何かしらのプログラミング経験がある方には逆にわかりやすいというあたりを狙ってます。
WordPressとは
WordPressはFacebookやNetflixがまだなかった時代、インターネットに自分のブログを投稿するためのCMS(contents management system)として生まれました。
また、テーマと呼ばれる呼ばれるwebサイトのテンプレートが有料や無料で公開されており、それらを用いればサクッと更新性のあるコンテンツが作れるため老若男女に非常に人気があります。
こちらの記事によると現在でも世界のwebサイトの34%はWordPressで構築されているそうです。
WordPressを使ってみる
百聞は一見にしかずと言う事で、ここからはハンズオン形式で進めます。ちなみに私の環境は
- MacOS Catalina 10.1.1
- MAMP 5.5
- php 7.37(MAMP)
- MySQL 5.7.26(MAMP)
- WordPress 5.3.1
でやっております。MAMPのインストールとXdebugの設定は済んでいる前提で進めます。(他の環境でも基本は一緒です)
環境構築
まずはWordPressの公式サイトからWordPress本体をダウンロードしてPCの任意の場所に移動し、MAMPでそのフォルダをdocument rootとして指定します。
MAMP > Preference > Web Serverタブをクリック > selectでディレクトリを指定する
設定出来たらMAMPのサーバーを起動してブラウザからlocalhost/phpmyadminにアクセスしてDBを作る。
データベースが作成出来たらブラウザからlocalhostにアクセスするとWordPressの初期化画面になってるので初期化する。
WordPressの管理画面にアクセスするための設定をする。メモしたらWordPressをインストール
localhostにアクセスしてこんな感じになってれば準備OK
これでローカル開発環境の準備はOKです。WordPressにもcliはあるのですが、最初のうちはMAMP安定かなと思います。
次のチャプターからは実際にWordPressをいじってみます。
WordPressを使ってみる
ここからは管理画面からWordPressを触ってみます。
テーマを変えてみる
WordPressはテーマと呼ばれるテンプレートのまとまりを切り替える事でサイトをガラリと変える事が出来ます。これも百聞は一見にしかずと言う事で試してみます。
管理画面の左側のパネル内の『外観』をクリック。Twenty Seventeenにマウスホバーすると選択できるのでテーマとして有効化する。
この状態でブラウザからlocalhostを確認する。するとサイトの見た目が変わっている。
このようにWordPressはテーマと呼ばれるwebサイトのテンプレートを読み込んで有効化することで、見た目や構造を変化させることができます。
世界中のデベロッパーがテーマを作って公開しているのでそれらを使ってサクッと作ることもできますし、逆に自分でテーマを作ることもできます。
記事を投稿してみる
次はブログを投稿してみます。
左側のパネルから投稿 > 新規追加を選択
選択すると投稿画面が表示されます。ここにタイトルと記事の内容を入れたら公開してみる
トップページを見てみると今作った記事が入ってきてるのがわかります。
記事そのもののページが表示されます。ここでurlに注目。日本語のURLが設定されています。これがどこで設定されているかと言うと、一旦管理画面に戻ります。
WordPressでは管理画面から投稿のURLを設定する仕組みになってるのです
また、記事を分類するためのカテゴリーも設定出来ます。投稿 > カテゴリー から試しにテスト1 ~ テスト3カテゴリを作成
テスト投稿をいくつか作ってそれぞれカテゴリーを設定してみます
この状態でトップページを見てみると記事が差し込まれてるのがわかるので、適当な記事をクリックする
記事の中にカテゴリーっぽいリンクがあるのでそれをクリックしてみる
すると選択されたカテゴリだけの一覧ページのような物が出来てます。
注目すべき点は__urlを管理画面上から設定する__ところです。ルーティング的な物は一体どうなっているのでしょうか?次のチャプターでいよいよ本題であるWordPressの仕組みについて説明します。
WordPressの仕組み
次に本題であるWordPressの仕組みを解説します。お好きなテキストエディタでMAMPで指定しているドキュメントルート(WordPress本体)のディレクトを開いてください。この中の
wp-content > themes > twentyseventeen(現在選択されているテーマ)の中を弄りならが説明します。
最初に知りたかった事①: WordPressのURLはデータベースに対するクエリ
まず一番最初に知りたかった事はWordPressをインストールしたサイトに対するリクエスト(URL)はDBに対するクエリになると言う事。
説明のためにテーマのフォルダの中にtest.phpを作ってブラウザで直接URLを叩いてみます。
するとお探しのページが見つかりませんとなります。
URLはuniform resource locatorの略、リソースの位置を指しているはずなのでこの動きは直感に反します。
なぜこの動きになるかざっくり言うと
__WordPressはURLをパースしてクエリとして扱う__からです。
localhost/phpmyadminを叩いてWordPressのDBを見てみます。
テーブルが12個ありますが、WordPressの管理画面から投稿した情報はwp_postsテーブルの中に入っているのでテーブルをみてみます。
管理画面から投稿した記事そのものはpost_contentカラム、タイトルはpost_titleカラムに入っているのがわかると思います。また先ほど設定したカテゴリーはwp_term_relationsipsテーブルの中で投稿のidと紐付けられています。
要するにWordPressはリクエストがきたらパースしてこれらのテーブルを走査するルールになっているので、静的なページすら管理画面から登録しなければ認められないのです。
参考:データベース構造 - WordPress Codex 日本語版_
次はもう少し詳しくルーティング(?)の仕組みを見てみます。
最初に知りたかった事②:ルーター的な存在とその仕組み
URLがDBへのクエリになっている事はわかりましたが、リクエストに対するビューの出し分けはどのようになっているのでしょうか。一旦テキストエディタを開いてテーマ内のファイルをみてみます。
いくつかのファイルがあり、その中のいくつかにはHTMLが書かれているので、なんとなくビューなんだろうなとわかります。問題はこれらがリクエストに応じてどのように出しわけされるかですが、__WordPressはテンプレート階層__と言う仕組みを利用して出しわけをしています。https://wpdocs.osdn.jp/テンプレート階層より引用
乱暴な言い方をすると、リクエストに対するビューの出し分けはphpファイルの名前で決まります
直感に反するでしかないので実際にテーマ内のファイルをいじってみます。
twentyseventeenフォルダの直下にcategory.phpを作ります。
そしてブラウザに戻ってカテゴリー一覧ページを開いてみます。
トップページから投稿を開く
今作ったcategory.phpが表示されるのがわかります。
エディタに戻ってcategory.phpを消去し、ブラウザを再読み込みしてみると戻ります。
これはテンプレート階層のルール的にカテゴリー一覧ページへのリクエストが来たら
- category.phpを返す
- なかったらarchive.phpを返す
- それもなかったら最終的にindex.phpを返す
って感じのルールになっているためです。
要するに__リクエストに対するビューの出しわけの階層構造化されたルールを__テンプレート階層とWordPressが定義しているのです。
ちなみに本当のルーティングはWordPress直下のwp_includes > template-loader.phpに記述されていますが、大分見慣れない感じなのでいじらない方が吉です。
次はビューとモデルの紐付けをWordPressがどのように行っているかみます。
最初に知りたかった事③: DBから取得したデータはどこにあるのか
WordPressはURLがパースされてDBから自動的にデータが取得されると書きましたが、実際にどのようにデータがビューに差し込まれるのかみていきます。
wp-content > themes > twentyseventeen > index.phpをエディタで開きます。これがtwentyseventeenのトップページで使われているテンプレートです。
さらにこの中の
<?php
if ( have_posts() ) :
/* Start the Loop */
while ( have_posts() ) :
the_post();
/*
* Include the Post-Format-specific template for the content.
* If you want to override this in a child theme, then include a file
* called content-___.php (where ___ is the Post Format name) and that will be used instead.
*/
get_template_part( 'template-parts/post/content', get_post_format() );
endwhile;
the_posts_pagination(
array(
'prev_text' => twentyseventeen_get_svg( array( 'icon' => 'arrow-left' ) ) . '<span class="screen-reader-text">' . __( 'Previous page', 'twentyseventeen' ) . '</span>',
'next_text' => '<span class="screen-reader-text">' . __( 'Next page', 'twentyseventeen' ) . '</span>' . twentyseventeen_get_svg( array( 'icon' => 'arrow-right' ) ),
'before_page_number' => '<span class="meta-nav screen-reader-text">' . __( 'Page', 'twentyseventeen' ) . ' </span>',
)
);
else :
get_template_part( 'template-parts/post/content', 'none' );
endif;
?>
if(have_posts())から始まるこの部分が投稿のデータを表示しているコードです。さらにwhile( have_posts() ):から始まるループの中で
get_template_part( 'template-parts/post/content', 'none' );
つまりインクルードしているので、画面との関係は
のようになります。
さてここでひとつ問題があります。
__DBから取得されたデータはどこにあるのか?__です。
例えばLaravelであれば
<?php
namespace App\Http\Controllers;
use DB;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* アプリケーションの全ユーザーレコード一覧を表示
*
* @return Response
*/
public function index()
{
$users = DB::table('users')->get();
return view('user.index', ['users' => $users]);
}
}
https://readouble.com/laravel/5.1/ja/queries.htmlより引用
のようになっていて
$users = DB::table('users')->get();
この部分でDBのレコードがオブジェクト的な物で返ってきてて
foreach ($users as $user) {
echo $user->name;
}
の形で取れそうだなと想像がつきますが、WordPressの方は$user->nameのような記述が一切ないのでDBから取得したデータがどこにあるのかさっぱりわからずモヤモヤするのでまたWordPressのindex.phpをいじって確認します。
すると$postsが10個のWp_Postをもつ配列になっていて$postには一つのWp_Postが入っている事が分かります。この__$postsこそDBから返ってきたデータを管理する変数__です。
念のためWp_postをcodexで確認します。
するとこのような記述が
$examplePost = get_post();
echo $examplePost->post_content; // 悪い例
echo apply_filters( 'the_content', $examplePost->post_content ); // 良い例
さらにIDを取得するのは良いけどpost_contentやpost_titleは直接参照しないように、ループ内ならthe_content、ループ外ならapplyfiltersを使えと書いてあります。なぜか気になるのでthe_contentを調べてみます。
the_contentはwp-includes/post-template.phpに定義されているのでみてみます。
やってる事としてはapply_filters()の返り値をちょっと加工して返しています。
apply_filtersはざっくり説明するとイベントトリガーです。イベントが発火されて、イベントに紐づくいろいろな処理が実行されている、くらいの認識で良いと思います。
なので$post->contentと直接参照するとそれらのthe_contentイベントに紐づく他の処理が実行されなくなるので非推奨になっていると思われます(定かではない)。
大分冗長になってしまいましたが__データベースから取得したデータは$postsの中にあります__が直接参照しない方が良いので結果的にどこに何があるか知る意味はなく、思考停止でWordPressが定義してる通りにやるのが良いのかもしれません。
まとめ
- WordPressのurlはDBに対するクエリになっている
- url毎のビューの出し分けは有効化されているテーマ内のphpファイルの名前で決まる。このルールをテンプレート階層と呼ぶ
- urlに紐づくDBのデータは$postsと$post変数に保存される。しかしこの変数は直接参照しない方が良い
他にも書きたい事はいろいろとありますが、最初に知りたかった事としてはこの辺りかなと個人的には思ってます。
さいごに
WordPressは一般的なフレームワークのようなMVCがなく、それぞれの仕組みに独自の名前がついているなどエンジニアとしてはとっつきにくい部分がありますが、実はcliがあったりrest apiが用意されていたりもします。
また、日常生活の文脈においては、友達の飲食店のwebサイトをサクッとつくってあげられたりすれば、それはそれでエンジニア冥利につきるのではないでしょうか。
WordPressをより深く知りたい方はこちらの書籍が非常に参考になります。
以上になります。ご高覧ありがとうございました。