WordPress開発をしてみよう

# はじめに
この記事で書くのは、Wordpressでゴリゴリにコーディングする話です。

Wordpressの機能でできることや、プラグインでできそうなことはわざわざコードを書く必要はないですが、必要に迫られることがあるかもしれません。
たとえば、プラグインAで作ったデータ構造が複雑すぎて、組み合わせて使う予定だったプラグインBでうまく使えないとか。
特定の機能を作りたい場合があるかもしれないですね。

## Wordpressってなに？
以下抜粋。https://ja.wordpress.org/ より
> WordPress とは
WordPress (ワードプレス) は、ブログから高機能なサイトまで作ることができるオープンソースのソフトウェアです。
世界中で使われる最高の信頼
Web 上の43%のサイトが WordPress を使っています。個人ブログから大規模なニュースサイトまで用途はさまざまです。

## WordPressをローカルでちょっと試すときにオススメなアプリ
https://localwp.com/

これを入れればすぐにローカルでサイトが立ち上げられます。

## コード触る時はこれを使ってます
https://azure.microsoft.com/ja-jp/products/visual-studio-code/


# 軽くコードを書いてみよう
おためしで`akasatana`というサイトを作ってみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952155/6c0b2ddf-10d3-d083-e09b-922ddb33ef63.png)
これが管理画面です。左メニューのPagesからページを作成します。

今回はKumaページを作ってみました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952155/fc7eb466-f337-2e93-4beb-de83e37091fc.png" width="49%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952155/2d72fada-4827-7ced-6a3a-4db022fd7306.png" width="49%">

`/kuma`ではアクセスできますが`/kumasan`ではアクセスできません。
これを`/kumasan`でもアクセスできるようにします。

## テーマに処理を書く

使用しているテーマ/functions.phpに処理を書きます。
参考 [Theme Functions](https://developer.wordpress.org/themes/basics/theme-functions/)

### 使用しているテーマを確認する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952155/81e6cefb-5035-de8a-ec6b-e35d9bee2cea.png)
`wp-admin/themes.php`で確認することができます。
ここではTwenty Twenty-ThreeがActivateされてます。

### 使用しているテーマ/functions.phpの場所
siteのfolderはこのような構成になっているはずです。
```
wp-content/
wp-admin/
wp-includes/
...
index.php
```
より詳しい情報はこちら [WordPress のコードはどのように構成されているか](https://make.wordpress.org/core/handbook/contribute/codebase/#how-code-in-wordpress-is-organized)

<details><summary>localを使っていて siteのfolderがわからないとき</summary>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952155/9bc24d41-5050-3e22-56a4-644bb4b91446.png)
サイト名の下のGo to site folderでどこにあるかがわかります。
app/public下にあります。
</details>

`wp-content/themes/`配下にテーマのディレクトリがあります。
```
wp-content/themes/
├── index.php
├── twentytwentyone
├── twentytwentythree
└── twentytwentytwo
```
例のサイトではこのようになってます。
現在Activateしているテーマは`Twenty Twenty-Three`なので、`twentytwentythree/functions.php`に処理を書きます。
`twentytwentytwo`,`twentytwentyone`はもともと`functions.php`があるので、下記の緑掛けの箇所を追記してください。

```diff_php:functions.php
<?php
+ add_action('init', 'rewrite_rules');
+ 
+ function rewrite_rules() {
+ 	add_rewrite_rule(
+ 	  '^kuma',
+ 	  'index.php?pagename=kuma',
+ 	  'top'
+ 	);
+ }
```

## 追加したコードの解説

### add_actionとは

WordPress開発をするために知っておくべきことがあります。
フックです。 フックはWordPressの処理フローのさまざまなポイントに独自の処理を差し込むための仕組みです。
フックにはアクションとフィルターの2種類があります。
**add_action()** と **add_filter()** 関数を呼ぶことで処理を登録できます。第1引数に処理を差し込むタイミング、第2引数に差し込む処理を指定します。
アクションとフィルターの違いについてですが、大きな違いは、アクションは値を返しませんが、フィルターは値を返します。詳しく知りたい方は[こちら](https://developer.wordpress.org/plugins/hooks/)

### add_actionで何をしている？
```php:functions.php
add_action('init', 'rewrite_rules');
```

第1引数で`init`を指定しています。WordPress の読み込みが完了した後、ヘッダーが送信される前に発生します。[initについて](https://developer.wordpress.org/reference/hooks/init/)
第2引数で`function rewrite_rules`を指定しているので、WordPress の読み込みが完了した後、 **rewrite_rules()** が呼び出されます。

### rewrite_rulesで何をしている？
```php:functions.php
function rewrite_rules() {
	add_rewrite_rule(
	  '^kuma',
	  'index.php?pagename=kuma',
      'top'
	);
}
```

**rewrite_rules()** は1つの関数を呼び出します。[add_rewrite_rule()](https://developer.wordpress.org/reference/functions/add_rewrite_rule/)です。第1引数の正規表現に合致するURLの場合に、第2引数のURLのページを表示します。第3引数はルールの優先度です。
コードを追加しただけでは、rewrite_rulesは効かないので、この段階ではまだ`/kumasan`は404になります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952155/4c2cb09e-a8df-a305-5ce7-3620302a58e2.png" width="49%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952155/f947c27f-1d5a-33b6-bce5-a73a2ebf6fbe.png" width="49%">

**wp-admin/options-permalink.php** にアクセスしてSave Changesボタンをクリックします。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952155/27edb542-bfe5-c7fa-d16f-a5f70612645d.png" width="49%">

これでrewrite_rulesが反映されて、`/kumasan`でも200になるようになりました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952155/72ba363a-d503-f526-a28f-7bb51f7a39a7.png" width="49%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952155/5c2727c7-a1b1-d8e0-6af3-612acfc2a505.png" width="49%">



# Pluginを作る

管理画面にクリスマスまでのカウントダウンを表示するプラグインを作ってみましょう。

## プラグインフォルダとファイルを作る
Countdownという名前のプラグインを作ります。
```console
wordpress $ cd wp-content/plugins
plugins $ mkdir countdown
plugins $ touch countdown/countdown.php
```

## プラグインのヘッダーを書く
```php:countdown.php
<?php
/**
 * Plugin Name: Countdown
 */
```
今回は最小限でプラグインの名前だけ書きましょう。他には、バージョンや作成者などの情報が定義できます。
参考: https://developer.wordpress.org/plugins/plugin-basics/header-requirements/

`wp-admin/plugins.php`を確認してみましょう。
Countdownが追加されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952155/bfcdf145-623e-799f-803a-2f8d5fff9aba.png)

Descriptionがないのは寂しいので、追加してみましょう。
```diff_php:countdown.php
 <?php
 /**
  * Plugin Name: Countdown
+ * Description: 管理画面にクリスマスまでのカウントダウンを表示します。
  */
```

`wp-admin/plugins.php`をリロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952155/039321a9-e682-9aa6-78eb-244fe91910b2.png)
Activateを押して有効化しましょう。
この段階ではまだ処理が入ってないので、管理画面にクリスマスまでのカウントダウンは表示されません。

## クリスマスへのカウントダウンを実装しよう

最終目標はこんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952155/e032cccc-714b-df51-074d-f77271ac5fff.png)

### 表示部分の処理を書く

ファイルを作成しましょう。
```console
plugins $ cd countdown
countdown $ mkdir admin
countdown $ touch admin/admin.php
```

```php:admin.php
<?php
/**
 * 管理画面のための処理を書くファイル
 */

/**
 * @link https://developer.wordpress.org/reference/hooks/all_admin_notices/
 */
add_action('all_admin_notices', 'the_countdown');

/**
 * クリスマスまでのカウントダウンを表示する
 *
 * @return void
 */
function the_countdown() {
  $now = date_time_set(date_create('now', wp_timezone()), 0, 0, 0, 0);
  $xmas = date_time_set(date_create_from_format('m-d', '12-25', wp_timezone()), 0, 0, 0, 0);
  $diff = date_diff($now, $xmas);
  if (wp_date('m') !== 12 || $diff->invert === 1) {
    return;
  }
?>
  <div class="countdown">
    <?php the_xmas_line();?>
    <p class="countdown__content">
      クリスマスまであと<span class="countdown__date"><?php echo $diff->format('%a'); ?></span>日
      <?php the_countdown_img(); ?>
    </p>
    <?php the_xmas_line(); ?>
  </div>
<?php
}

/**
 * カウントダウンの画像を表示する
 *
 * @return void
 */
function the_countdown_img() {
  $img_file = 'assets/img/' . wp_date('d') . '.png';

  if(!file_exists(COUNTDOWN_PATH . $img_file)) {
    $img_file = 'assets/img/not_found.png';
  }
?>
  <img class="countdown__img" src="<?php echo COUNTDOWN_URL . $img_file;?>">
<?php
}

/**
 * カウントダウンをデコレーションするラインを表示する
 *
 * @return void
 */
function the_xmas_line() {
?>
  <div class="countdown__line">
    <img src="<?php echo COUNTDOWN_URL . 'assets/img/line_hiiragi.png';?>">
    <img src="<?php echo COUNTDOWN_URL . 'assets/img/line_bell.png';?>">
  </div>
<?php
}
```
管理画面のお知らせを表示するhookで`the_countdown`を呼び出しています。
12月ではない、または、クリスマスを過ぎている場合には何も表示されません。
`あとx日`のxには、クリスマス当日を含みません。クリスマス当日には`あと0日`と表示されます。
画像は、表示日の名前のファイルを表示します。たとえば、今日が12/1なら、`countdown/assets/img/1.png`が表示されます。12/11なら、`countdown/assets/img/11.png`。
表示日の名前のファイルがない場合には、`countdown/assets/img/not_found.png`を表示します。

各関数の頭についている`the_`はwordpressでprintされる関数でよく使われてる接頭辞です。

もしこの記事を12月以外で試す場合には、`the_countdown`関数のreturnをコメントアウトしてください。
```php:admin.php
  if (wp_date('m') !== 12 || $diff->invert === 1) {
    // return;
  }
```

今の段階では、admin.phpが呼ばれることはありません。
countdown.phpで呼び出す必要がありますが、その修正は最後に行います。

### styleを追加しよう

ファイルを作成しましょう。
```console
countdown $ mkdir core
countdown $ touch core/settings.php
```

```php:settings.php
<?php
/**
 * 初期設定を行うためのファイル
 */

namespace CountDown;

add_action('init', 'CountDown\\load_css');

function load_css() {
  if(is_admin()){
    wp_enqueue_style('countdown_admin', COUNTDOWN_URL . 'assets/css/admin.css', [], true);
  }
}
```
管理画面の時は`plugins/countdown/assets/css/admin.css`を呼び出すように指定しました。
これはお試しのコードなので、cssを毎回再読み込みする指定を`wp_enqueue_style`の4つ目の引数でしています。

cssファイルを作成しましょう。
```console
countdown $ mkdir assets
countdown $ mkdir assets/css
countdown $ touch assets/css/admin.css
```

```css:admin.css
.countdown {
  align-items: center;
  display: flex;
  justify-content: center;
  width: 100%;
}

.countdown__content {
  width: 20%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0px 4px;
}

.countdown__date {
  color: red;
  font-size: 150%;
  margin: 0px 2px;
}

.countdown__img {
  width: 50%;
}

.countdown__line {
  width: 40%;
  display: flex;
  flex-wrap: wrap;
}

.countdown__line > img {
    width: 100%;
}

.countdown__line:first-child {
  justify-content: end;
}
```

### 画像ファイルを追加しよう
フォルダを作成しましょう。
```console
countdown $ mkdir assets/css/img
```

この記事では[いらすとや](https://www.irasutoya.com/)さんの画像を使用させていただきました。
https://www.irasutoya.com/2021/01/chopper.html
https://www.irasutoya.com/2015/12/blog-post_96.html
https://www.irasutoya.com/2015/12/blog-post_69.html

img配下に、not_found.png、line_bell.png、line_hiiragi.png、{日付}.pngを追加しましょう。

### 定義の追加とファイル呼び出しをしよう
```diff_php:countdown.php
 <?php
 /**
  * Plugin Name: Countdown
  * Description: 管理画面にクリスマスまでのカウントダウンを表示します。
  */

+ define('COUNTDOWN_PATH', plugin_dir_path( __FILE__ ));
+ define('COUNTDOWN_URL', plugin_dir_url( __FILE__ ));
+ 
+ include COUNTDOWN_PATH . 'core/settings.php';
+ include COUNTDOWN_PATH . 'admin/admin.php';
```

## 確認
管理画面のいろんなページを見てみましょう:point_up:

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952155/c342faf3-b0b1-ffc0-bff6-c187ebf9b72e.png" width="49%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952155/0aecabb6-224f-d89e-7c43-0a460626f237.png" width="49%">

管理画面以外には影響がないことも確認しましょう:v:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952155/11bcf2e7-cc32-3d9a-2039-5addcbc3a867.png)


# おわり
どうでしたでしょうか？簡単にプラグインの追加方法など記載しました。
冒頭でふれた `たとえば、プラグインAで作ったデータ構造が複雑すぎて、組み合わせて使う予定だったプラグインBでうまく使えないとか。` ですが、Wordpressのプラグインの中には、独自のhookを用意しているものもあり、処理を差し込んだりできます。
Wordpress上の開発はなかなか面白いので、興味があればぜひやってみてください。

## おまけ
日付計算の部分、初めはこう書いてました。
```php:admin.php
  $now = date_create('now', wp_timezone());
  $xmas = date_create_from_format('m-d', '12-25', wp_timezone());
  $diff = date_diff($now, $xmas);
```

11/29の段階であと25日と表示されていました。おかしいな。
お試しコード追加
```php:admin.php
  $now2 = date_create_from_format('m-d', '11-29', wp_timezone());
  print $now->format(DATE_ATOM).':'.date_diff($now, $xmas)->format('%a').'<br>';
  print $now2->format(DATE_ATOM).':'.date_diff($now2, $xmas)->format('%a').'<br>';
```
`比較する日付:残り日数`を表示する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952155/735dd70e-847e-e5b0-c0f4-b296515b2146.png)
nowは25日でnow2は26日...？

お試しコード変更、ミリ秒まで表示してみる
```php:admin.php
  $now2 = date_create_from_format('m-d', '11-29', wp_timezone());
  print $xmas->format(DATE_RFC3339_EXTENDED).'<br>';
  print $now->format(DATE_RFC3339_EXTENDED).':'.date_diff($now, $xmas)->format('%a').'<br>';
  print $now2->format(DATE_RFC3339_EXTENDED).':'.date_diff($now2, $xmas)->format('%a').'<br>';
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952155/35b484fa-550f-876c-ec18-2897ba37d551.png)
`date_create('now', wp_timezone());`はミリ秒まで生成されるが、`date_create_from_format('m-d', '12-25', wp_timezone());`は秒までなため、比較に差が出ていた。

```php:admin.php
  $now = date_time_set(date_create('now', wp_timezone()), 0, 0, 0, 0);
  $xmas = date_time_set(date_create_from_format('m-d', '12-25', wp_timezone()), 0, 0, 0, 0);
  $diff = date_diff($now, $xmas);
```
最終的に、時〜ミリ秒に0を設定し計算する形にしました。