
created_at
カラムを更新させるシステムには気をつけろ!秒数まで明示的に更新しないとアーカイブの順番が入れ替わりまくるぞ!
事象
私が開発に取り組んでいたプロジェクトは、ユーザーの問い合わせを記録し、新しい投稿順に表示するWebアプリケーションでした。
ユーザーが過去の日付の問い合わせを書き忘れていた場合には、その問い合わせを後からでも書き直せるようにするため、システムは問い合わせの作成日時(created_at
)をユーザーが更新可能にしていました。
しかし、投稿を更新すると、「新しい投稿順」の表示順序が変動してしまうという事象が発生しました。
原因
問題は、投稿のcreated_at
フィールドが更新されるとき、一部の情報(具体的には「秒」)が失われてしまうという点でした。
具体的には、フロントエンド(Vue.jsを使用)から送信される新たなcreated_at
の値には「秒」が含まれていないため、元のcreated_at
の秒数が更新時に失われてしまっていました。これはフロントエンドで使用していたVuetifyのコンポーネントv-time-picker
が秒数を扱うオプションを提供していないためでした。
解決策
この問題の解決策は、created_at
の値を更新する前に、既存の値から秒数を取得し、それを新しいcreated_at
に設定するという方法でした。つまり、新しいcreated_at
の日付と時刻はリクエストからのデータを使用し、秒数だけは既存の値を保持します。バックエンド(Laravelを使用)のコードは以下のようになります。
// リクエストから送信されたcreated_atに基づいて新しいcreated_atを作成
$newCreatedAt = Carbon::createFromFormat('Y-m-d H:i', $request->created_at);
// 既存の秒数を新しいcreated_atに設定
$newCreatedAt->second($existingCreatedAt->second);
// リクエストに新しいcreated_atを設定
$request->merge(['created_at' => $newCreatedAt]);
まとめ
この方法で、データの一部を保持しながら、他の部分を更新するという目的を達成することができました。
今回のケースは、フロントエンドのコンポーネントが秒数を扱えないために生じた問題を、バックエンドのコードの修正で解決するという例でした。
開発環境
- バックエンド: PHP (Laravel)
- フロントエンド: Vue.js (Vuetify)