Laravel 复制包括关系但保持原始时间戳

Laravel replicate including relationships but maintain original timestamps

我正在尝试复制 Laravel 8 中的记录及其关系。但我想保留原始记录的时间戳。我可以在主记录上执行此操作,但所有关系上的时间戳都设置为复制记录的日期时间。我还设置了一些观察器,我不希望它们在复制发生时触发。

$order = App\Models\Order::with('comments', 'tracking_details')->find(4096);


$clone = $order->replicate()->fill([
    'tracking_number' => null,
    'created_at' => $order->created_at,
    'updated_at' => $order->updated_at,
]);

$clone->saveQuietly();


foreach ($order->comments as $comment) {
    App\Models\Comments::withoutEvents(function() use ($clone, $comment) {
        $clone->comments()->create($comment->toArray());
    });
}


foreach ($order->tracking_details as $details) {
    App\Models\TrackingDetails::withoutEvents(function() use ($clone, $details) {
        $clone->tracking_details()->create($details->toArray());
    });
}

如有任何帮助,我们将不胜感激。

不确定这是否有效,但您是否尝试过在模型中禁用时间戳?

public $timestamps = FALSE;

如果您希望您的模型能够通过 create() 方法保存时间戳,您应该将 created_atupdated_at 属性添加到模型的 $fillable 中。参考:Making properties mass assignable

created_at 和 updated_at 列是 Laravel 开箱即用的默认时间戳,在数据库和您的数据库中创建一个默认为 null 的 cloned_at 列数据库模型,将其添加到可填充的 属性,然后您可以在数据库中简单地插入数据,其中 created_at 和 updated_at 值将被解析为逗号分隔值,在检索数据时,您可以从 CSV 中拆分和修改字符串并将其解析为 Carbon 格式,这是一个肮脏但可能的解决方案。

对于关系,您可以改用查询生成器。

// main record

$order = Order::find(4096);

$clone = $order->replicate()->fill([
    'tracking_number' => null,
    'created_at' => $order->created_at,
    'updated_at' => $order->updated_at
]);

$clone->saveQuietly();

// comments relationship

$comments = Comments::toBase()->where('order_id', $order->id)->orderBy('id')->get()->map(function ($item) use ($clone) {
    unset($item->id);

    $item->order_id = $clone->id;

    return (array) $item;
});

Comments::insert($comments->toArray());

// tracking_details relationship

$trackingDetails = TrackingDetails::toBase()->where('order_id', $order->id)->orderBy('id')->get()->map(function ($item) use ($clone) {
    unset($item->id);

    $item->order_id = $clone->id;

    return (array) $item;
});

TrackingDetails::insert($trackingDetails->toArray());

在这种情况下,您不使用 eloquent,这意味着不会触发任何事件,您将保留原始记录时间戳。