アプリケーションを移行している際に、DBの処理をEloquentに移行しました。
タイムスタンプの部分でエラーが出続けたため、試行錯誤した結果です。
現象
いまのサービスのtimestamp型に入っているデータで、ミリ秒まで入っているデータとミリ秒がないデータがありPHPのDatetime型にうまく変換してくれない状態です。
データベースのデータを修正する方針でもよかったけど、他のプロジェクトも直す必要があったため、Eloquent側で対応してみました。
登録する際になるエラーを対応した内容です。
対応内容
Modelクラスの$datasにカラムを指定すると、Carbonに変換してくれるみたいですね。
$datesに指定すると、asDateTime関数に処理が任されるため、オーバーライドして、全部ミり秒ありに変換して対応です。
<?php
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
class AppEloquent extends Illuminate\Database\Eloquent\Model
{
public function getDateFormat()
{
return 'Y-m-d H:i:s.u';
}
/**
* オーバーライド
* @param [type] $value [description]
* @return [type] [description]
*/
protected function asDateTime($value)
{
// If this value is already a Carbon instance, we shall just return it as is.
// This prevents us having to re-instantiate a Carbon instance when we know
// it already is one, which wouldn't be fulfilled by the DateTime check.
if ($value instanceof Carbon) {
return $value;
}
// If the value is already a DateTime instance, we will just skip the rest of
// these checks since they will be a waste of time, and hinder performance
// when checking the field. We will just return the DateTime right away.
if ($value instanceof DateTimeInterface) {
return new Carbon(
$value->format('Y-m-d H:i:s.u'), $value->getTimezone()
);
}
// If this value is an integer, we will assume it is a UNIX timestamp's value
// and format a Carbon object from this timestamp. This allows flexibility
// when defining your date fields as they might be UNIX timestamps here.
if (is_numeric($value)) {
return Carbon::createFromTimestamp($value);
}
// If the value is in simply year, month, day format, we will instantiate the
// Carbon instances from that format. Again, this provides for simple date
// fields on the database, while still supporting Carbonized conversion.
if ($this->isStandardDateFormat($value)) {
return Carbon::createFromFormat('Y-m-d', $value)->startOfDay();
}
// 追加した内容
$value = date( $this->getDateFormat(), strtotime($value));
// Finally, we will just assume this date is in the format used by default on
// the database connection and use that format to create the Carbon object
// that is returned back out to the developers after we convert it here.
return Carbon::createFromFormat(
str_replace('.v', '.u', $this->getDateFormat()), $value
);
}
}