Laravel8でDBから取り出した値のタイムゾーンがずれる時の対処法

2022-06-05

2022-06-05

4 min read

Laravel

背景

Laravel8でDBのcreated_atのカラムを参照しようとした際、タイムゾーンが9時間ずれる。

Larave6では、config/app.phptimezoneAsia/Tokyoに変更したら、日本時間になっていたような気がしたので少し悩みました。

/*
|--------------------------------------------------------------------------
| Application Timezone
|--------------------------------------------------------------------------
|
| Here you may specify the default timezone for your application, which
| will be used by the PHP date and date-time functions. We have gone
| ahead and set this to a sensible default for you out of the box.
|
*/
'timezone' => 'Asia/Tokyo',

Date Serializationの仕様が変更になってることが原因

どうやらLarave7からDate Serializationの仕様が変わっていたみたいです。

詳しくはこちら

モデルをオーバーライドする

正しくタイムゾーンを切り替えるには、モデルをserializeDate()メソッドを使ってオーバーライドする必要があるみたいです。

今回はトレイトを用いた方法でオーバーライドしてみます。

ちなみにトレイトとは、PHPで実装されているコードを再利用するための仕組みです。

以下PHP マニュアルから抜粋

トレイトは、PHP のような単一継承言語でコードを再利用するための仕組みのひとつです。 トレイトは、単一継承の制約を減らすために作られたもので、 いくつかのメソッド群を異なるクラス階層にある独立したクラスで再利用できるようにします。 トレイトとクラスを組み合わせた構文は複雑さを軽減させてくれ、 多重継承や Mixin に関連するありがちな問題を回避することもできます。

userテーブルのcreated_atの値をY-m-d H:iの形で参照したい場合

<?php

namespace App\\Models;

use DateTimeInterface;

trait SerializeDate
{
    /**
     * Prepare a date for array / JSON serialization.
     *
     * @param  \\DateTimeInterface  $date
     * @return string
     */
    protected function serializeDate(DateTimeInterface $date)
    {
        return $date->format('Y-m-d H:i:s');
    }
}
class User extends Model
{
    use SerializeDate;

    protected $casts = [
        'created_at' => 'datetime:Y-m-d H:i',
    ];

    ・
    ・
}

これにより、Userテーブルのcreated_atのタイムゾーンのずれが解消され、「datetime:Y-m-d H:i」の形のフォーマットで参照できるようになしました。

最後に

Laravelではこちらのサイトの左メニューの「Prologue > Upgrade Guide」から各バージョンのアップグレードガイドを確認することができます。

FWのバージョンを上げた際の変更点や影響度を確認できるので、ご興味ある方は覗いてみてください。