WordPressに入門する時、最初に知りたかったいくつかの事


# はじめに
初めまして。フリーランスのテクニカルディレクターをしております。Daiskyと申します。ジーズアカデミーアドベントカレンダー13日目に投稿する予定だったWordPressについて書こうと思います。

G'sではWordPressが話題に上がる事は殆どないので逆に面白いかなと思うのと、初めてWordPressについて勉強した時に、情報が全体的に冗長だなと感じたので

- 要所だけをかいつまんで
- サクッと入門できる
- ハンズオン形式

でWordPressの説明をできればと思います。
一般的なIT用語とMVCフレームワークの話をちょっとしているので全くの初心者の方には向かないと思いますが、何かしらのプログラミング経験がある方には逆にわかりやすいというあたりを狙ってます。


# WordPressとは
WordPressはFacebookやNetflixがまだなかった時代、インターネットに自分のブログを投稿するためのCMS（contents management system）として生まれました。

また、テーマと呼ばれる呼ばれるwebサイトのテンプレートが有料や無料で公開されており、それらを用いればサクッと更新性のあるコンテンツが作れるため老若男女に非常に人気があります。

[こちらの記事](https://kinsta.com/jp/wordpress-market-share/)によると現在でも世界の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の公式サイト](https://ja.wordpress.org/)からWordPress本体をダウンロードしてPCの任意の場所に移動し、MAMPでそのフォルダをdocument　rootとして指定します。



MAMP > Preference > Web Serverタブをクリック > selectでディレクトリを指定する
<img width="534" alt="MAMP_と_ちょっとした画像加工に最適！便利すぎるSkitchの使い方まとめ｜ferret.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/c23001e6-669a-b105-0660-3cacc24e7bc2.png">

設定出来たらMAMPのサーバーを起動してブラウザからlocalhost/phpmyadminにアクセスしてDBを作る。
<img width="724" alt="localhost_8888___localhost___phpMyAdmin_4_9_0_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/d78cafd7-83ac-dd9a-1017-b5b7c01c95ef.png">


データベースが作成出来たらブラウザからlocalhostにアクセスするとWordPressの初期化画面になってるので初期化する。
<img width="800" alt="スクリーンショット 2019-12-13 18.14.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/2846d7cb-0933-f2e2-e37d-7e77eacfef1e.png">

ユーザー名とパスワード名はMAMPの場合どちらもroot
<img width="830" alt="スクリーンショット 2019-12-13 18.16.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/bb08281b-20b1-6f9c-4dea-ef35f1df5a70.png">

問題がなければこの画面になるはず。インストール実行する。
<img width="798" alt="スクリーンショット 2019-12-13 18.17.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/4943a65d-82fe-334b-e7ee-ff0ed9b1ee69.png">


WordPressの管理画面にアクセスするための設定をする。メモしたらWordPressをインストール
<img width="763" alt="WordPress_›_インストール.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/d4a3abe0-4625-67d0-9f35-34e74c440c0d.png">


問題がなければログインする
<img width="811" alt="スクリーンショット 2019-12-13 18.25.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/640d7c59-02b2-929f-0aad-bebac120001c.png">

先ほど設定したid pwを入れてログイン
<img width="543" alt="スクリーンショット 2019-12-13 18.26.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/49f92fb2-c5ec-557c-20e9-ac8b91f7889d.png">


こんな感じになってればOK
<img width="2002" alt="スクリーンショット 2019-12-13 18.27.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/210d6fed-a7b8-a031-5ce3-4ee26cf1c84e.png">

localhostにアクセスしてこんな感じになってれば準備OK<img width="1992" alt="スクリーンショット 2019-12-13 18.30.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/f70aa8b7-9fe2-cbb7-60ba-54b1cfc2f9ea.png">


これでローカル開発環境の準備はOKです。WordPressにもcliはあるのですが、最初のうちはMAMP安定かなと思います。
次のチャプターからは実際にWordPressをいじってみます。

# WordPressを使ってみる
ここからは管理画面からWordPressを触ってみます。
### テーマを変えてみる
WordPressはテーマと呼ばれるテンプレートのまとまりを切り替える事でサイトをガラリと変える事が出来ます。これも百聞は一見にしかずと言う事で試してみます。

管理画面の左側のパネル内の『外観』をクリック。Twenty Seventeenにマウスホバーすると選択できるのでテーマとして有効化する。
<img width="1076" alt="テーマの管理_‹_test_wp_—_WordPress.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/a7140011-36ae-7222-6e19-5ed8bcfaf319.png">

Twenty Seventeenが有効化されている状態
<img width="1065" alt="スクリーンショット 2019-12-13 19.03.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/4e7e0bf3-5f29-a569-cbe9-70a75521591c.png">

この状態でブラウザからlocalhostを確認する。するとサイトの見た目が変わっている。
<img width="1079" alt="スクリーンショット 2019-12-13 19.05.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/23659015-9518-4a86-9314-7024e57bd312.png">

このようにWordPressはテーマと呼ばれるwebサイトのテンプレートを読み込んで有効化することで、見た目や構造を変化させることができます。

世界中のデベロッパーがテーマを作って公開しているのでそれらを使ってサクッと作ることもできますし、逆に自分でテーマを作ることもできます。


### 記事を投稿してみる
次はブログを投稿してみます。
左側のパネルから投稿 > 新規追加を選択
<img width="1074" alt="投稿_‹_test_wp_—_WordPress.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/31d935bf-7d0b-4e36-1eb9-884abda58475.png">


選択すると投稿画面が表示されます。ここにタイトルと記事の内容を入れたら公開してみる
<img width="1075" alt="新規投稿を追加_‹_test_wp_—_WordPress.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/f7eda841-8ee1-fbf5-1057-c4e546a37f5a.png">


トップページを見てみると今作った記事が入ってきてるのがわかります。
<img width="1184" alt="スクリーンショット 2019-12-14 13.41.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/24a7d808-0ed4-d55e-ee47-13fba513037b.png">

さらに記事のタイトルをクリックすると<img width="1178" alt="test_wp_–_Just_another_WordPress_site-2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/912218e2-12ff-4c30-a408-36a9761211e3.png">


記事そのもののページが表示されます。ここでurlに注目。日本語のURLが設定されています。これがどこで設定されているかと言うと、一旦管理画面に戻ります。
<img width="1184" alt="テスト投稿です_–_test_wp.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/c851380d-ed13-6d64-31d2-62c85a1bc400.png">




WordPressでは管理画面から投稿のURLを設定する仕組みになってるのです
<img width="1189" alt="投稿の編集_‹_test_wp_—_WordPress_と_辞書（8件見つかりました）.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/f5187a64-9f06-3a1b-4aad-5bdded4b3d3e.png">

また、記事を分類するためのカテゴリーも設定出来ます。投稿 > カテゴリー　から試しにテスト１ ~ テスト３カテゴリを作成<img width="1187" alt="カテゴリー_‹_test_wp_—_WordPress.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/8f3fec7b-cf73-f2df-827f-3336d9e028ae.png">

テスト投稿をいくつか作ってそれぞれカテゴリーを設定してみます
<img width="1183" alt="スクリーンショット 2019-12-14 14.09.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/52aea5e4-bd77-0541-7097-cc021bce2a15.png">


この状態でトップページを見てみると記事が差し込まれてるのがわかるので、適当な記事をクリックする
<img width="1190" alt="スクリーンショット 2019-12-14 14.10.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/888196cf-3b70-1ee4-9e27-b74bbd9e8d8c.png">

記事の中にカテゴリーっぽいリンクがあるのでそれをクリックしてみる
<img width="1186" alt="test3-3_–_test_wp.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/bd047581-e1dd-f461-56cf-2e848843d776.png">

すると選択されたカテゴリだけの一覧ページのような物が出来てます。
<img width="1183" alt="スクリーンショット 2019-12-14 14.13.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/51c48c90-c64f-3f8d-7ead-55c6738004cb.png">





注目すべき点は__urlを管理画面上から設定する__ところです。ルーティング的な物は一体どうなっているのでしょうか？次のチャプターでいよいよ本題であるWordPressの仕組みについて説明します。





# WordPressの仕組み

次に本題であるWordPressの仕組みを解説します。お好きなテキストエディタでMAMPで指定しているドキュメントルート（WordPress本体）のディレクトを開いてください。この中の
wp-content > themes > twentyseventeen（現在選択されているテーマ）の中を弄りならが説明します。
<img width="1687" alt="スクリーンショット_2019_12_14_14_30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/670c044f-cba0-9d69-4bbd-77fb2b13f80c.png">





## 最初に知りたかった事①：　WordPressのURLはデータベースに対するクエリ
まず一番最初に知りたかった事はWordPressをインストールしたサイトに対するリクエスト（URL）はDBに対するクエリになると言う事。

説明のためにテーマのフォルダの中にtest.phpを作ってブラウザで直接URLを叩いてみます。
<img width="926" alt="スクリーンショット_2019-12-25_21_08_02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/42d32881-36d3-c27f-96e7-aeda9d176a9b.png">

するとお探しのページが見つかりませんとなります。
<img width="1061" alt="スクリーンショット_2019-12-25_21_12_50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/49016f4f-e470-8a5a-dc38-965b8c870938.png">
URLはuniform resource locatorの略、リソースの位置を指しているはずなのでこの動きは直感に反します。

なぜこの動きになるかざっくり言うと
![Web 1920 – 291.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/a580f3b3-5260-1d7f-d5cb-22452ec815af.jpeg)
__WordPressはURLをパースしてクエリとして扱う__からです。

localhost/phpmyadminを叩いてWordPressのDBを見てみます。
<img width="1071" alt="スクリーンショット_2019-12-25_22_07_09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/ee54a672-74db-ce39-63a5-fe9051abbb9f.png">
テーブルが12個ありますが、WordPressの管理画面から投稿した情報はwp_postsテーブルの中に入っているのでテーブルをみてみます。
<img width="1071" alt="スクリーンショット_2019-12-25_22_09_39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/3c7506be-e365-2bf0-0c77-dc8658af3a82.png">

管理画面から投稿した記事そのものはpost_contentカラム、タイトルはpost_titleカラムに入っているのがわかると思います。また先ほど設定したカテゴリーはwp_term_relationsipsテーブルの中で投稿のidと紐付けられています。


要するにWordPressはリクエストがきたらパースしてこれらのテーブルを走査するルールになっているので、静的なページすら管理画面から登録しなければ認められないのです。
参考：[データベース構造 - WordPress Codex 日本語版](http://wpdocs.osdn.jp/%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E6%A7%8B%E9%80%A0)_


次はもう少し詳しくルーティング（？）の仕組みを見てみます。


## 最初に知りたかった事②：ルーター的な存在とその仕組み
URLがDBへのクエリになっている事はわかりましたが、リクエストに対するビューの出し分けはどのようになっているのでしょうか。一旦テキストエディタを開いてテーマ内のファイルをみてみます。

<img width="1137" alt="スクリーンショット_2019-12-25_22_26_28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/c02a8bdc-2db7-19b8-15a9-776ace881b50.png">
いくつかのファイルがあり、その中のいくつかにはHTMLが書かれているので、なんとなくビューなんだろうなとわかります。問題はこれらがリクエストに応じてどのように出しわけされるかですが、__WordPressはテンプレート階層__と言う仕組みを利用して出しわけをしています。

![1500px-wp-template-hierarchy.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/c0ff4e2f-36b1-977d-4bd9-7f17a8726a65.jpeg)https://wpdocs.osdn.jp/テンプレート階層より引用

乱暴な言い方をすると、__リクエストに対するビューの出し分けはphpファイルの名前で決まります__

直感に反するでしかないので実際にテーマ内のファイルをいじってみます。
twentyseventeenフォルダの直下にcategory.phpを作ります。
<img width="1137" alt="スクリーンショット_2019-12-25_22_55_38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/2fff91ab-8f21-74ce-8545-be95c41b7fcb.png">

そしてブラウザに戻ってカテゴリー一覧ページを開いてみます。
トップページから投稿を開く
<img width="589" alt="スクリーンショット_2019-12-25_22_59_07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/7efd6d7e-e150-d688-f03f-1d17cdd78552.png">

記事ページからカテゴリ一覧を開く
<img width="589" alt="スクリーンショット_2019-12-25_23_00_09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/a8096be9-bafd-8e12-ccc2-343a67835a4e.png">

今作ったcategory.phpが表示されるのがわかります。
<img width="1077" alt="スクリーンショット_2019-12-25_23_02_51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/4589e947-92b0-1572-77a2-8e5147c77e3d.png">

エディタに戻ってcategory.phpを消去し、ブラウザを再読み込みしてみると戻ります。
<img width="1076" alt="スクリーンショット_2019-12-25_23_06_03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/c59e95c4-ba4e-8c1b-47d5-7a6770393330.png">

これはテンプレート階層のルール的にカテゴリー一覧ページへのリクエストが来たら

- 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のトップページで使われているテンプレートです。
<img width="1077" alt="スクリーンショット_2019-12-26_1_10_22-2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/0964337e-536b-d768-1706-4c1f4896572a.png">
さらにこの中の

```index.php
<?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() ):から始まるループの中で

```php
get_template_part( 'template-parts/post/content', 'none' );
```
つまりインクルードしているので、画面との関係は
<img width="1072" alt="スクリーンショット_2019-12-26_1_27_50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/324cbf77-ab64-c591-0c44-fc95f91b0e98.png">
のようになります。

さてここでひとつ問題があります。

__DBから取得されたデータはどこにあるのか？__です。

例えばLaravelであれば

```php
<?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](https://readouble.com/laravel/5.1/ja/queries.html)より引用

のようになっていて

```php
$users = DB::table('users')->get();
```
この部分でDBのレコードがオブジェクト的な物で返ってきてて

```php
foreach ($users as $user) {
    echo $user->name;
}
```
の形で取れそうだなと想像がつきますが、WordPressの方は$user->nameのような記述が一切ないのでDBから取得したデータがどこにあるのかさっぱりわからずモヤモヤするのでまたWordPressのindex.phpをいじって確認します。

xdebugを使って３５行目で処理を止めます。
<img width="1362" alt="スクリーンショット_2019-12-26_9_53_27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/184c9ac7-5561-1d4f-7623-4496b6ff23c6.png">

すると\$postsが10個のWp_Postをもつ配列になっていて$postには一つのWp_Postが入っている事が分かります。この__$postsこそDBから返ってきたデータを管理する変数__です。

試しに$postのIDを直接echoしてみます。
<img width="1004" alt="スクリーンショット_2019-12-26_10_07_17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/122f3c02-8836-9205-0a6f-12377fa3d1d0.png">

記事のIDがechoされてるのが分かります。
<img width="1077" alt="スクリーンショット_2019-12-26_10_08_54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/a7125856-8683-c16f-0033-b572b51319b6.png">

念のためWp_postを[codex](https://wpdocs.osdn.jp/%E3%82%AF%E3%83%A9%E3%82%B9%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/WP_Post)で確認します。

するとこのような記述が

```php
$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に定義されているのでみてみます。
<img width="779" alt="スクリーンショット 2019-12-26 10.36.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219808/ff2cae2a-593c-4c2b-9b2a-faf946b9fcab.png">
やってる事としては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をより深く知りたい方は[こちらの書籍](https://gihyo.jp/book/2017/978-4-7741-8706-8)が非常に参考になります。


以上になります。ご高覧ありがとうございました。