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

合并多个Eloquent模型:以最新模型为基准填充空属性

优雅聚合Eloquent模型:以最新模型为基准填充非空属性

针对你需要合并多个Eloquent模型,用旧模型的非空数据填充最新模型空属性的需求,这里有几个比逐个遍历属性更高效的方案,完全贴合Laravel的Eloquent生态:

方法1:集合遍历+fill()批量填充

先获取所有需要合并的模型并按创建时间倒序排列(确保最新的模型在最前面),然后以它为基准,依次用其他模型的非空属性填充:

// 假设你的模型是User,先获取目标模型并按创建时间倒序
$models = User::whereIn('id', [1, 2, 5])->orderBy('created_at', 'desc')->get();

// 复制最新模型作为合并基准(避免修改原模型)
$mergedModel = $models->first()->replicate();

// 遍历剩余模型,填充非空属性
$models->slice(1)->each(function ($model) use ($mergedModel) {
    // 筛选当前模型的非空属性,且只保留基准模型允许填充的字段
    $fillableData = collect($model->getAttributes())
        ->filter(fn ($value) => !is_null($value) && $value !== '')
        ->only($mergedModel->getFillable())
        ->toArray();

    // 用fill()批量填充,自动遵守fillable规则,安全可靠
    $mergedModel->fill($fillableData);
});

// 现在$mergedModel就是你要的合并结果

方法2:自定义模型方法,复用合并逻辑

如果需要多次进行这类合并操作,可以在你的Eloquent模型里封装一个mergeWith()方法,让代码更整洁:

// 在你的模型类(比如User.php)中添加方法
public function mergeWith(self $otherModel): self
{
    $merged = $this->replicate();

    $fillableData = collect($otherModel->getAttributes())
        ->filter(fn ($value) => !is_null($value) && $value !== '')
        ->only($this->getFillable())
        ->toArray();

    $merged->fill($fillableData);

    return $merged;
}

// 使用示例:
$latestModel = User::find(5);
$olderModel1 = User::find(2);
$olderModel2 = User::find(1);

// 链式调用合并多个模型
$mergedModel = $latestModel->mergeWith($olderModel1)->mergeWith($olderModel2);

方法3:用集合reduce()一次性完成合并

利用Laravel集合的reduce()方法,可以更简洁地完成多模型的迭代合并:

$models = User::whereIn('id', [1, 2, 5])->orderBy('created_at', 'desc')->get();

$mergedModel = $models->reduce(function ($carry, $model) {
    // 第一次迭代时,把最新模型作为初始值
    if (is_null($carry)) {
        return $model->replicate();
    }

    // 筛选非空属性并填充
    $fillableData = collect($model->getAttributes())
        ->filter(fn ($value) => !is_null($value) && $value !== '')
        ->only($carry->getFillable())
        ->toArray();

    $carry->fill($fillableData);
    return $carry;
});

注意事项

  • 上述代码中的filter()逻辑是过滤null和空字符串,如果你需要处理其他“空”情况(比如0、false),可以根据业务需求调整过滤条件。
  • 使用getFillable()确保只填充模型允许批量赋值的字段,避免安全风险;如果你的模型设置了$guarded = [](允许所有字段填充),可以去掉only($mergedModel->getFillable())这一步。
  • replicate()方法会复制模型的所有属性和关联(如果需要的话),如果不需要关联,可以用replicate([])。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:53:26