【Laravel-Admin】カスタムフィールドを作る

Laravel-Adminを使った管理画面を運用しているのですが、用意されている既存フィールドでは要件に合わない時があります。

laravel-admin.org

例えば、年月日の月を管理したい場合です。

もちろん、月を管理するためのフィールドは初めから用意されています。
しかし、年を跨いで設定したい場合、月のみの扱う形式は使いづらいです。
また、入力時にはカレンダー(datetimepicker)で選択できるのですが、選択時に表示される形式も月のみなので歯痒い状態です。

Laravel-Adminのコアファイルを変更すれば対応自体はできますが、今後ライブラリのアップデートやクローンサイトを作る時の弊害になります。
可能であれば任意のフィールドを追加したいものです。

さて、
今回はLaravel-Adminに、カスタムフィールド(任意のフィールド)を追加する方法について記載します。

要件

検証した環境は下記です。

ライブラリ名 バージョン
Laravel-Admin v1.5.19
Laravel 5.5以上

実装仕様

冒頭でも触れましたが、年を跨ぐ事も考慮して、年と月を組み合わせて管理できるようにしたいです。
例えば、「対象月」を管理する項目を作るとします。

上記を対応する場合、既存の月を管理するフィールドでは次の不満点があります。

  • カレンダーの表示形式が月のみ、例えば1月の場合は「01」で保存。
  • 月部分だけ文字として保存される、カレンダーと同様に0埋めの数字で保存される

f:id:nakahashi_h:20201114161436p:plain

改善方針

理想としては次のような仕様にしたいです。

  • カレンダーの表示形式は「(選択された年)年(選択された月)月」 にしたい
  • 保存形式はDate型(YYYY-MM-DD)にしたい

公式ドキュメント

カスタムフィールドの作り方については下記で解説されています。
今回は、このドキュメントを参考にしながら進めていきます。

laravel-admin.org

カスタムフィールドを追加

自作のカスタムフィールドを追加したい場合は、App\Admin\Extensionsに属したクラスを作る必要があります。

Extensionsクラス用のディレクトリを用意

laravel-adminを導入すると、app配下にAdminディレクトリが作られます。
作成するExtensionsは、Admin配下のExtensionsディレクトリに設定する必要がありますので、ディレクトリを追加します。

app
└── Admin
   └── Extensions

カスタムフィールド用のクラス追加

実際の処理クラスを追加します。
今回はEncore\Admin\Form\Field\Dateの機能(バリデーションや登録処理)を流用したいので、Dateクラスのラッパーを作ります。

次のようなクラスを用意します。

<?php
// CustomMonth.php

namespace App\Admin\Extensions;

use Carbon\Carbon;
use Encore\Admin\Form\Field\Date;

class CustomMonth extends Date {
    // 取得したDateの変換フォーマット
    protected $format = 'YYYY年MM月';
    
    // DateTimeで変換するためのフォーマット
    public static $defaultFormat = 'Y年m月';
        
    // 登録前の処理
    // そのままだと、self::$formatの形式(YYYY年MM月)で保存されるので手動で置換
    public function prepare($value) {
        $result = null;
        if ($value) {
            $date = \DateTime::createFromFormat(self::$defaultFormat, $value);
            $result = $date->format('Y-m-d');
        }
        return $result;
    }
}

作成したCustomMonth.phpを、前項で作成したapp/Admins/Extentions/配下に設置します。

app
└── Admin
   └── Extensions
      └── CustomMonth.php

カスタムフィールドを呼び出せるように調整

作成したフィールドをapp/Admin/bootstrap.phpに追加します。

<?php
Encore\Admin\Form::forget(['map', 'editor']);

// 関数名を「customMonth」として追加
\Encore\Admin\Form::extend(
    'customMonth',
    \App\Admin\Extensions\CustomMonth::class
);

// 省略

関数呼び出し

実際に作成した関数を呼び出します。
前項でbootstrapに追加した、customMonthを呼び出します。

<?php
// 省略
protected function form()
{
    // 変更
    $form->customMonth('target_at', 対象月)
        ->default(date('Y-m-d'));
        
    // 省略
}

これで、次のように「(選択された年)年(選択された月)月」の形式で表示されるようになります。

f:id:nakahashi_h:20201114161528p:plain

一覧表示の見た目も変える

現状ではDBに保存された形式で表示されます。
「2020-11-01」のように指定していない日にちまで出てしまいます。

f:id:nakahashi_h:20201114161611p:plain

この表示も「2020年11月」のような形式にしたいです。

表示の変更は、display()で指定します。

<?php
protected function grid() {
    $grid->target_at('対象月')
        ->display(function($targetAt) {
            if(! strptime($targetAt, '%Y-%m-%d')) {
            return null;
            }
        
            // 日付型から対象のフォーマットに変更
            $result = new \DateTime($targetAt);
            return $result->format(CustomMonth::$defaultFormat);
        });
} 

これで、一覧表示時も変換したい形式で表示できます。

f:id:nakahashi_h:20201114161637p:plain

©︎2017-2018 WebSandBag