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

Laravel中firstOrNew结合关联查询实现数据增改的问题

搞定user_sales表的同款「存在更新/不存在创建」逻辑

嘿,我完全get你的需求!既然user_buys用firstOrNew实现了「同用户、同item、同日期的条目存在就更新value,不存在就新建」的逻辑,把这套逻辑搬到user_sales表其实非常简单,甚至还能优化得更通用,给你分几种情况说:

直接复用逻辑(最快上手)

因为两张表结构类似,你只需要把模型类从UserBuy换成对应的UserSale就行,代码几乎一模一样:

// 处理user_sales表的条目
$entry = UserSale::firstOrNew([
    'item_id' => $item_id,
    'user_id' => Auth::id(),
    'date' => $date
]);
$entry->value = $value;
$entry->save();

只要你的UserSale模型正确关联到user_sales表(Laravel默认会按类名复数映射,没特殊情况不用额外配置),这段代码就能完美复刻user_buys的逻辑。

进阶封装:避免重复代码

如果以后还有更多类似结构的表,总复制粘贴代码太麻烦,不如封装一个通用方法,放在工具类或者你的基础模型里:

// 通用的「存在更新/不存在创建」方法
function upsertEntry(string $modelClass, array $uniqueConditions, array $updateData)
{
    $entry = $modelClass::firstOrNew($uniqueConditions);
    // 批量赋值要更新的字段
    foreach ($updateData as $key => $value) {
        $entry->$key = $value;
    }
    $entry->save();
    return $entry;
}

// 用的时候就很清爽:
// 处理user_buys
upsertEntry(UserBuy::class, [
    'item_id' => $item_id,
    'user_id' => Auth::id(),
    'date' => $date
], ['value' => $value]);

// 处理user_sales
upsertEntry(UserSale::class, [
    'item_id' => $item_id,
    'user_id' => Auth::id(),
    'date' => $date
], ['value' => $value]);

更高效的方案:用Laravel的upsert方法(Laravel 8+可用)

如果你用的是Laravel 8及以上版本,推荐用upsert方法,它直接利用数据库的INSERT ... ON DUPLICATE KEY UPDATE逻辑,只需要一次SQL操作,比firstOrNew先查后改更高效:

// user_sales的upsert写法
UserSale::upsert(
    // 要插入/更新的数据
    [
        [
            'item_id' => $item_id,
            'user_id' => Auth::id(),
            'date' => $date,
            'value' => $value
        ]
    ],
    // 用来判断条目标识的唯一字段组合
    ['item_id', 'user_id', 'date'],
    // 当条目存在时需要更新的字段
    ['value']
);

⚠️ 注意:用upsert的话,必须给你的user_sales表在item_id、user_id、date这三个字段上创建联合唯一索引,否则数据库会允许重复插入,触发报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:41:03