在 Laravel 6 中,在不更改框架默认时区:Asia/Shanghai 的情况下,日期时间格式调整为 UTC (二)
1、由于程序主体的时区为:Asia/Shanghai,但是在一些模型中打算存储 UTC 的时区值
2、参考:https://www.shuijingwanwq.com/2022/07/11/6776/ ,发现仍然不符合预期。在第 7 步骤的调整后。同样的程序,在队列中运行后,字段 updated_at 的值,其对应的时区有时候仍然为:Asia/Shanghai,大部份时候的时区为:UTC。如图1
3、暂时调整为如下实现,当 $value 为字符串时,则返回当前的 UTC 时间。
1 2 3 4 5 6 7 8 9 10 | /** * 转换时区 * * @param $value * @return string */ private function transTz($value = null): string { return now()->utc()->toDateTimeString(); } |
4、发现仍然存在时区为:Asia/Shanghai 的情况。不过发现时区在不断变换的模型,可能是因为在队列中不断地 save() 所导致。大概在队列中同一个模型执行了 5 次以上的 save() 方法。如图2
5、最终决定采用沿用原有步骤 4 的方案。不过步骤 4 的方案不适用于 delete() 方法,其生成的 SQL 中,deleted_at 的值的时区仍然为:Asia/Shanghai。如图3
1 | update `table` set `deleted_at` = '2023-01-12 11:19:17' where `id` = 534 |
6、决定仍然使用修改器,因为其在同一个队列中,同一个模型仅会执行一次 delete() 方法。
1 2 3 4 5 6 7 8 9 10 | /** * 设置删除时间 * * @param $value * @return void */ public function setDeletedAtAttribute( $value ) { $this ->attributes[ 'deleted_at' ] = $value ? now()->utc()->toDateTimeString() : $value ; } |
7、最后发现生成的 SQL 不符合预期,时区仍然为:Asia/Shanghai
1 | update ` table ` set `deleted_at` = '2023-01-12 16:05:00' where `id` = 531 |
8、由于软删除使用了 trait SoftDeletes,尝试覆写方法:runSoftDelete()
编辑前:
1 | $ time = $this->freshTimestamp(); |
编辑后:
1 | $ time = Date ::now( 'UTC' ); |
9、发现生成的 SQL 符合预期,时区为:UTC
1 | update ` table ` set `deleted_at` = '2023-01-12 08:09:02' where `id` = 534 |
10、在有需要使用 UTC 时区的模型中,最后实现如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | use Illuminate\Database\Eloquent\SoftDeletes; class ThemeInstallation extends Model { use SoftDeletes; /** * Perform the actual delete query on this model instance. * * @return void */ protected function runSoftDelete() { $query = $this ->setKeysForSaveQuery( $this ->newModelQuery()); $time = Date ::now( 'UTC' ); $columns = [ $this ->getDeletedAtColumn() => $this ->fromDateTime( $time )]; file_put_contents (storage_path() . '/logs/SoftDeletes.runSoftDelete-' . microtime(true) . '-' . mt_rand() . '.txt' , print_r( $time , true), FILE_APPEND | LOCK_EX); $this ->{ $this ->getDeletedAtColumn()} = $time ; if ( $this ->timestamps && ! is_null ( $this ->getUpdatedAtColumn())) { $this ->{ $this ->getUpdatedAtColumn()} = $time ; $columns [ $this ->getUpdatedAtColumn()] = $this ->fromDateTime( $time ); } $query ->update( $columns ); $this ->syncOriginalAttributes( array_keys ( $columns )); } } |
11、由于有多个模型需要用到 UTC 时区,为了避免代码冗余,新建一个 trait 文件:/app/Traits/UtcSoftDeletes.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | <?php namespace App\Traits; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Facades\ Date ; trait UtcSoftDeletes { use SoftDeletes; /** * Perform the actual delete query on this model instance. * * @return void */ protected function runSoftDelete() { $query = $this ->setKeysForSaveQuery( $this ->newModelQuery()); $time = Date ::now( 'UTC' ); $columns = [ $this ->getDeletedAtColumn() => $this ->fromDateTime( $time )]; $this ->{ $this ->getDeletedAtColumn()} = $time ; if ( $this ->timestamps && ! is_null ( $this ->getUpdatedAtColumn())) { $this ->{ $this ->getUpdatedAtColumn()} = $time ; $columns [ $this ->getUpdatedAtColumn()] = $this ->fromDateTime( $time ); } $query ->update( $columns ); $this ->syncOriginalAttributes( array_keys ( $columns )); } } |
12、在有需要使用到 UTC 的模型中,引入新的 trait 文件,查看未使用新的 trait 与使用了新的 trait 的区别。相差 8 小时。如图4
近期评论