You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Laravel的firstOrCreate仅按Y-m-d日期判断新增记录?

Laravel按日期(不含时分秒)实现firstOrCreate逻辑的方法

问题原因

你之前的做法失效,核心原因是created_at一般为datetime/timestamp类型:当你传入Y-m-d格式的Carbon日期时,Laravel会自动补全时分秒为00:00:00,导致只有数据库中created_at恰好是当天零点的记录才会被匹配到,其他时间的记录都无法命中,所以每次都会新增。

解决方案

方法一:先查询再创建(最稳妥直接)

用whereDate方法精准匹配日期部分,找不到记录时再创建:

use Carbon\Carbon;
use App\Models\YourModel; // 替换为你的实际模型类

$userEmail = 'user@example.com';
$today = Carbon::today();

// 查询当天该用户的记录
$record = YourModel::where('user_email', $userEmail)
    ->whereDate('created_at', $today)
    ->first();

// 无匹配记录则创建新条目
if (!$record) {
    $record = YourModel::create([
        'user_email' => $userEmail,
        'created_at' => Carbon::now(), // 也可根据需求设为Carbon::today()
        // 其他需要填充的字段
    ]);
}

方法二:封装查询范围(提升复用性)

在模型中定义查询范围,简化重复调用逻辑:

// 在你的模型类中添加
public function scopeForUserAndDate($query, $userEmail, $date)
{
    return $query->where('user_email', $userEmail)
        ->whereDate('created_at', $date);
}

使用时的代码会更简洁:

$record = YourModel::forUserAndDate('user@example.com', Carbon::today())
    ->first() ?? YourModel::create([
        'user_email' => 'user@example.com',
        'created_at' => Carbon::now(),
        // 其他字段
    ]);

方法三:结合原生SQL函数(贴近firstOrCreate写法)

针对MySQL数据库,可以用DATE()函数提取日期部分作为查询条件,结合firstOrCreate:

$record = YourModel::firstOrCreate(
    [
        'user_email' => 'user@example.com',
        \Illuminate\Support\Facades\DB::raw('DATE(created_at)') => Carbon::today()->toDateString(),
    ],
    [
        // 新增记录时的默认字段配置
        'created_at' => Carbon::now(),
    ]
);

注意:不同数据库的日期转换函数不同,比如PostgreSQL需用CAST(created_at AS DATE),请根据你的数据库类型调整。

内容的提问来源于stack exchange,提问作者sfarzoso

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 10:32:21