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_at
和 updated_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,这意味着不会触发任何事件,您将保留原始记录时间戳。
我正在尝试复制 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_at
和 updated_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,这意味着不会触发任何事件,您将保留原始记录时间戳。