【Drupal】生年月日フィールドの元号表示対応（Field Formatterを実装してみよ）

## はじめに
Drupalの日付や時刻を扱う際、簡単なものであれば `環境設定` > `地域と言語`内の「日付と時間のフォーマット」から、日付や時刻のFormatを作成することができますよね。

<details><summary>↑↑
がピンとこない人はこちら</summary>

![スクリーンショット 2024-06-08 23.16.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/bad5d901-99a3-c23e-3fda-a25f2e23717b.png)
</details>

ただ、和暦表示や年度変換など、Drupal標準だと対応できないものもあります。

こんな場面で対応できるのが、「FieldFormatter」です。

今回は「Field Formatter」の実装について触れてみたいと思います。

## 0. 前提(対象)
- Drupalのモジュール開発をしたことがある
- PluginAPIへの理解

## 1. Field Formatter とは
Fieldのデータをフォーマットし、表示できるようにするためのものです。

https://www.drupal.org/docs/creating-custom-modules/creating-custom-field-types-widgets-and-formatters/create-a-custom-field-formatter

今回の「和暦表示」や「年度変換」も`HOOK`システムで局所的な対応をしてもいいですが、多くの箇所で使うようなシステムであればPluginとして実装する意義がありそうですよね。

## 2. 環境
今回は、以下のバージョンで実装を行いました。
Drupal 10.2.7
Drush 12.5

## 3. 実装
### ER図
今回のテーブル構成はこんな感じ。

**Member(Drupal標準のUserエンティティを使用しても可)**

| Field  | Type   |
|--------|--------|
| name   | プレーンテキスト |
| field_birthday | 日付と時刻（日付のみ） |

### 実装
それでは実装してみましょー。
#### 手順１. ModuleのSetup。
`drush`がいい感じのものを用意してくれています。
ここまではCLI操作のみでできます。

```shell-session
drush generate plugin:field:formatter
```
対話形式でModule名やClass名を指定してください。
```shell-session
 Module machine name:
 ➤ sample_module_formatter

 Plugin label:
 ➤ SampleModule(和暦対応)

 Plugin ID:
 ➤ japanese_era_date

 Plugin class [WarekiFormatter]:
 ➤ JapaneseEraDateFormatter

 Make the formatter configurable? [No]:
 ➤ No
```
``{root}/web/modules/*``を確認してみてください。
たったコマンド一つでモジュールが用意できたと思います。

有効化もお忘れなく。
```shell-session
drush en sample_module_formatter
```

#### 手順2. Pluginを日付フィールドに対応させる
Pluginを「日付と時刻」フィールドタイプを指定する必要があります。
``drush generate``で作成されたFormatterファイル内のAnnotationを指定します。

```php:JapaneseEraDateFormatter.php
/**
 * 和暦対応.
 *
 * @FieldFormatter(
 *   id = "japanese_era_date",
 *   label = @Translation("和暦対応"),
 *   field_types = {"datetime"},   // ← ここ
 * )
 */
final class JapaneseEraDateFormatter extends FormatterBase {
  // ~ 省略 ~
}
```
デフォルトでは、「string」になっているはずです。

#### 手順3. GUIでFormatterを選択
「日付と時刻」フィールドを設定しているエンティティタイプのビューモード設定画面にて、作成したFormattarを選択してみましょう。
手順2のAnnotation指定に間違いがなければ、この時点で選択ができるようになります。

![スクリーンショット 2024-06-08 21.30.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/cd292494-5ec0-4413-1c42-0bf442fa9df0.png)
↑↑ 「和暦対応」という選択肢が増えていますね。

選択して保存しましょう。

#### 手順4. 出力変更の実装
`JapaneseEraDateFormatter::viewElements`メソッド内で、`#markup`を指定していますよね。
こちらを加工すれば出力が変わるようになっています。

```php:JapaneseEraDateFormatter
/**
 * {@inheritdoc}
 */
public function viewElements(FieldItemListInterface $items, $langcode) {
  $elements = [];
  foreach ($items as $delta => $item) {
    $date = new DrupalDateTime($item->date);

    // Convert the date to Japanese era format here.
    $markup = $this->convertDateTime($date);

    $elements[$delta] = ['#markup' => $markup];
  }

  return $elements;
}

/**
 * 日付データの加工.
 */
private function convertDateTime(DrupalDateTime $date) {
  // 日付のフォーマット.
  $date_format = $date->format('Y年m月d日');
  // 元号.
  $era = Era::fromDateTime($date);
  $era_format = $era->getJapaneseName();

  return $date_format . '(' . $era_format . '生まれ)';
}
```

`foreach文`内の`$item`にフィールド値に関する情報が入っています。
デバッグして確認してみてください。

**※ 元号変換ロジックについては、本記事の趣旨がずれてきますので解説を省きます。**

[Github](https://github.com/umekikazuya/sample-module-field_formatter)にサンプルコードを載せていますので気になる方はぜひ活用ください。

実装は完了です。

## 4. 表示確認
実際に表示を見てみましょう。

![スクリーンショット 2024-06-08 21.29.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/214d749e-1e2c-5dad-9c71-f7f4d0eda457.png)

ちゃんと表示されていますね。実装がうまくいっているようです。（よかった）

はい、私は平成12年生まれです。

## 5. コード
今回のコードはGithubにあげています。
参考になれば幸いです。

https://github.com/umekikazuya/sample-module-field_formatter

## 6. まとめ
いかがでしたか？

今回は、元号を題材に「日付」フィールドの入力値に応じてFormattarで表示を変える方法を紹介しました。

もちろん、フィールドのデータのみならずEntityの情報を拾うことができますので他のフィールドとの組み合わせで表示のカスタマイズができたりもするかと思います。

元号変換ロジックについては以下の記事で解説しています。こちらもぜひ。

https://qiita.com/umekikazuya/items/31eabf4f3749eb7a3d16