Laravel の Eloquent 検証($dateFormat と $dates)
前回は Laravel の Eloquent を勉強するため、環境構築を行いました。
今回は日付に関する内容で、モデルのプロパティである$dateFormat
や$dates
について検証を行いました。
$dateFormat の検証
参考:Eloquent: Getting Started - Laravel - The PHP Framework For Web Artisans
created_at
やupdate_at
のフォーマットを変更した時の検証を、以下の2パターンで行います。
- デフォルトの timestamp にミリ秒も利用する(例:2019-05-06 10:10:22.123456)
- Unix 時間を利用する(例:1557105050)
デフォルトの timestamp にミリ秒も利用する
$dateFormat
プロパティにY-m-d H:i:s.u
を指定します。
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class User extends Model { public $incrementing = false; protected $keyType = 'string'; protected $guarded = [ 'created_at', 'updated_at', ]; protected $dateFormat = 'Y-m-d H:i:s.u'; // ← ここを追加 }
- マイグレーションファイルの編集
デフォルトの$tabe->timestamps();
では秒までしか登録されませんが、以下のようにtimestamps
に桁数を渡す事で、小数部分も登録されるようになります。
<?php public function up() { Schema::create('users', function (Blueprint $table) { $table->string('id', 36)->primary(); $table->string('last_name'); $table->string('first_name'); $table->timestamps(6); // ← 桁数を指定 }); }
- データ作成
ユーザーを1件登録します。
<?php User::create([ 'id' => Uuid::uuid4()->toString(), 'last_name' => '山田', 'first_name' => '太郎', ]);
このようにミリ秒も含めて登録される事が確認出来ました。
Unix 時間を利用する
- モデルの設定
$dateFormat
プロパティにU
を指定します。
<?php class User extends Model { 〜 略 〜 protected $dateFormat = 'U'; // ← ここだけ変更 }
- マイグレーションファイルの編集
Unix 時間が登録されるように、$tabe->timestamps();
を以下のようにinteger
を使って定義するようにします。
<?php public function up() { Schema::create('users', function (Blueprint $table) { $table->string('id', 36)->primary(); $table->string('last_name'); $table->string('first_name'); $table->integer('updated_at'); $table->integer('created_at'); }); }
- データ作成
ユーザーを1件登録します。
<?php User::create([ 'id' => Uuid::uuid4()->toString(), 'last_name' => '山田', 'first_name' => '太郎', ]);
このように Unix 時間で登録される事が確認出来ました。
感想
外部のサービスと連携する時など、サービスによっては日時のフォーマットが異なる場合もあるかと思います。 そして、外部サービスから受け取ったデータをそのまま DB へ保存したい時などに使えるのではないかと思いました。
$dates の検証
参考:Eloquent: Mutators - Laravel - The PHP Framework For Web Artisans
Eloquent は、データを取得するとデフォルトでcreated_at
とupdated_at
をCarbon
インスタンスへ変換してくれます。
created_at
とupdated_at
以外に日時を扱うカラムを追加した際に、$dates
でそのカラムを指定する事で、その指定したカラムもCarbon
インスタンへ変換してくれるようになります。
マイグレーションファイルおよびデータの準備
User のマイグレーションファイルに、以下のようなカラムを追加して検証を行います。
- カラム名:
logged_at
(Null を許可)- ユーザーがログインした日時を保存しておく想定
<?php public function up() { Schema::create('users', function (Blueprint $table) { $table->string('id', 36)->primary(); $table->string('last_name'); $table->string('first_name'); $table->timestamp('logged_at')->nullable(); // ← 追加 $table->timestamps(); }); }
次に、テーブルを作成後、以下のようなレコードを作成しておきます。
$dates を設定しなかった場合の挙動
まずは、User モデルに$dates
を設定せずにデータを取得してみます。
<?php $user = User::find('01a2b401-b03b-4471-9fe3-c015e22f0552'); logger($user->logged_at); logger(gettype($user->logged_at));
出力内容
[2019-05-06 03:33:23] testing.DEBUG: 2019-05-06 03:27:48 [2019-05-06 03:33:23] testing.DEBUG: string
このようにデフォルトではstring
で取得されます。
そのため、例えば2019年05月06日
と表示したい場合に、自前でCarbon
を使ったりdate
関数を駆使してフォーマットの変換を行わなければなりません。
$dates を設定した場合の挙動
それでは、以下のように User モデルに$dates
を設定します。
<?php class User extends Model { 〜 略 〜 protected $dates = [ 'logged_at' ]; }
再度、出力内容を少し変えて取得してみます。
<?php $user = User::find('01a2b401-b03b-4471-9fe3-c015e22f0552'); logger($user->logged_at); logger(get_class($user->logged_at)); logger($user->logged_at->format('Y年m月d日'));
出力内容
[2019-05-06 04:06:02] testing.DEBUG: 2019-05-06 03:27:48 [2019-05-06 04:06:02] testing.DEBUG: object [2019-05-06 04:06:02] testing.DEBUG: Illuminate\Support\Carbon [2019-05-06 04:06:02] testing.DEBUG: 2019年05月06日
このようにCarbon
インスタンスへ変換されたものが取得され、format
メソッドで簡単に書式を整える事ができました。
感想
正直言いますと、今まで取得したstring
の日付を頑張ってフォーマットしていました・・・。
もっと早く知っていれば!と後悔です。
おまけ
プライマリキーは UUID で
検証で使う User モデルの id を、デフォルトのもの(int)ではなく、以前勉強したUUID
で利用できるようにしています。
モデルの置き場所を変更
モデルはapp/Models
下に置くように変更しました。
参考:【Laravel】Model ファイルのディレクトリ構成変更時にやること | ブロックチェーンエンジニアのブログ
実行された SQL を確認したい
下記参考サイトを真似させて頂きました。
※ 出力される SQL の実行時間($query->time
)の単位はミリ秒
です。
<?php namespace App\Providers; use Illuminate\Support\Facades\{DB, Log}; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * サービスプロバイダの登録 * * @return void */ public function register() { // } /** * アプリケーションサービスの初期処理 * 参考サイト:https://daiki-sekiguchi.com/2018/07/26/laravel-sql-log/ * * @return void */ public function boot() { if (config('app.env') !== 'production') { DB::listen(function ($query) { Log::info("Query Time:{$query->time}ms] $query->sql"); Log::info($query->bindings); }); } } }