Laravel默认将模型日期序列化为ISO 8601格式,可通过全局Carbon::serializeUsing、模型$dateFormat或字段级$casts灵活自定义,推荐使用$casts实现精细控制且不影响存储。

Laravel模型日期序列化,简单来说,就是当你把一个模型实例转换成数组或JSON格式输出时(比如通过API接口返回数据),模型里的日期字段(例如
created_at
updated_at
Carbon
Laravel在日期序列化这块,默认做得挺好的,它会把
created_at
updated_at
$dates
Carbon
1. 全局日期格式化: 如果你希望整个应用中所有模型的日期字段都遵循同一个自定义格式,可以在
AppServiceProvider
boot
Carbon
use Carbon\Carbon;
use Illuminate\Support\Facades\Schema; // 如果需要,可以引入
public function boot()
{
// ... 其他 boot 方法内容
Carbon::serializeUsing(function ($carbon) {
return $carbon->format('Y-m-d H:i:s'); // 比如,我们都想要这种格式
});
// 或者,如果你只关心 JSON 序列化,且使用 Laravel 9+
// Json::encodeUsing(function ($value) {
// if ($value instanceof Carbon) {
// return $value->format('Y-m-d H:i:s');
// }
// return null; // 或者其他默认处理
// });
}这种方式很“霸道”,一旦设置,全局生效。这意味着所有通过
toArray()
toJson()
2. 模型级别日期格式化: 如果你只想针对某个特定模型改变日期格式,可以在模型中定义
$dateFormat
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
/**
* The storage format of the model's date columns.
*
* @var string
*/
protected $dateFormat = 'Y-m-d H:i:s'; // 这个Post模型的所有日期字段都会用这个格式
// ... 其他模型属性和方法
}这个
$dateFormat
3. 字段级别日期格式化(推荐): 这是我个人最喜欢也最推荐的方式,因为它足够精细,可以针对模型中的每一个日期字段设置不同的格式,而且不会影响数据库存储格式。通过
$casts
datetime
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Event extends Model
{
/**
* The attributes that should be cast.
*
* @var array
*/
protected $casts = [
'start_date' => 'datetime:Y-m-d H:i', // 精确到分钟
'end_date' => 'datetime:Y-m-d H:i:s', // 精确到秒
'published_at' => 'date:Y-m-d', // 只显示日期
];
// ... 其他模型属性和方法
}这种方式的强大之处在于,它只影响序列化输出和从数据库读取时的类型转换,不会干预数据库实际存储的格式(数据库通常还是存储
datetime
TIMESTAMP
start_date
Carbon
Y-m-d H:i
说实话,刚接触Laravel的时候,我有时也会纳闷,为什么我的
created_at
2023-10-27T10:30:00.000000Z
ISO 8601 格式其实是个非常棒的选择,尤其对于API和跨系统通信来说。它具有明确的结构,包含了日期、时间,甚至毫秒级精度和时区信息(那个
Z
具体来说,Laravel模型会将
created_at
updated_at
deleted_at
$dates
Carbon
Carbon
Carbon
jsonSerialize()
所以,当你看到
2023-10-27T10:30:00.000000Z
Date
moment.js
date-fns
要自定义日期输出格式,我们手头有几个工具,选择哪个取决于你的具体需求和“影响范围”。我通常会从最细粒度的控制开始考虑,如果不行再往上走。
1. 字段级别的精细控制(首选): 如前所述,
$casts
class Product extends Model
{
protected $casts = [
'available_from' => 'datetime:Y-m-d', // 仅日期
'promotion_ends_at' => 'datetime:Y-m-d H:i', // 日期和时间(分钟)
'last_updated_by_admin' => 'datetime:Y-m-d H:i:s P', // 包含时区偏移
];
}这种方式的好处在于,它不会影响数据库存储,也不会影响其他模型的日期格式。它只在模型被转换成数组或JSON时生效,提供了极高的灵活性。
2. 模型级别的统一格式: 如果你发现一个模型里所有日期字段都需要统一的格式,那么
$dateFormat
class Order extends Model
{
protected $dateFormat = 'Y-m-d H:i:s'; // 订单模型的所有日期都用这个格式
}这个设置会覆盖全局的
Carbon::serializeUsing()
datetime
TIMESTAMP
Y-m-d H:i:s
$dateFormat
3. 全局统一格式(慎用): 当你真的、真的希望整个应用的所有日期输出都保持一个固定格式时,才考虑在
AppServiceProvider
Carbon::serializeUsing()
// AppServiceProvider.php
public function boot()
{
Carbon::serializeUsing(function ($carbon) {
return $carbon->format('Y-m-d H:i:s');
});
}这个方法是最“粗暴”的,它会影响所有
Carbon
Carbon
Carbon
总的来说,从精细到粗略,
$casts
$dateFormat
Carbon::serializeUsing()
$casts
处理日期序列化,看似简单,实则暗藏玄机。我踩过的坑,多多少少都跟对时间、时区、以及Laravel内部机制理解不够透彻有关。
1. 时区混乱: 这是最常见的“坑”。Laravel默认将所有日期存储为UTC时间,并在从数据库读取时,根据
config/app.php
timezone
Z
调试方法:
dd($model->created_at)
dd
Carbon
Date
timezone
UTC
dd($model->toArray())
dd($model->toJson())
config/app.php
timezone
UTC
2. $dates
published_at
$dates
$casts
Carbon
Carbon
调试方法:
protected $dates = ['published_at'];
protected $casts = ['published_at' => 'datetime'];
dd(gettype($model->published_at))
object
Carbon\Carbon
3. $dateFormat
$dateFormat
调试方法:
INSERT
UPDATE
4. 覆盖 toArray()
jsonSerialize()
toArray()
jsonSerialize()
Carbon
调试方法:
toArray()
jsonSerialize()
format()
Carbon
5. 前后端格式不一致的预期: 这算不上Laravel的坑,更多是前后端协作的坑。后端可能默认输出ISO 8601,而前端期望的是
YYYY-MM-DD
调试方法:
$casts
日期序列化是个小细节,但处理不好,会给整个应用带来不少麻烦。多利用
dd()
Carbon
以上就是Laravel模型日期序列化?日期序列化如何自定义?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号