Laravel でデータベースの1行をカンタンにコピーする方法はありませんか?
はい。あります。
こちらに。
http://stackoverflow.com/questions/34257741/laravel-copy-record-and-duplicate-with-new-values
なのですが、意訳と補足をさせていただきます。
【基本】->replicate() を使う
$oldrow = MyModel::find($id);
$newrow = $oldrow->replicate();
$newrow->some_column = 'new data';
$newrow->save();
これが基本形です。
なのですが、ちょっと疑問が幾つか……。
id は更新しなくて大丈夫なんですか?
ついつい、以下のようにやりたくなります(上記のサイトでもやってます)。でないと、同じIDを持たせたままだったら、コピーじゃなくて上書きになってしまうのでは?
$oldrow = MyModel::find(2145);
$newrow = $oldrow->replicate();
$newrow->id = null;
$newrow->some_column = 'new data';
$newrow->save();
いやいや、それじゃ replicate した意味ないっすよ。そこはちゃんと考えられていて、このようになっています。
$oldrow = MyModel::find(2145);
$newrow = $oldrow->replicate();
var_dump( $oldrow->id ); // 2145
var_dump( $newrow->id ); // NULL
$newrow->some_column = 'new data';
$newrow->save();
タイムスタンプ created_at updated_at は更新しないとですよね?
これは必要でしょ!(上記のサイトでも以下略)
$oldrow = MyModel::find(2145);
$newrow = $oldrow->replicate();
$newrow->created_at = date('Y-M-D H:m:s');
$newrow->some_column = 'new data';
$newrow->save();
いやいや、意外と大丈夫です。
$oldrow = MyModel::find(2145);
$newrow = $oldrow->replicate();
var_dump( $oldrow->created_at ); // 2016-09-26 23:15:33
var_dump( $oldrow->updated_at); // 2016-09-26 23:15:33
var_dump( $newrow->created_at ); // NULL
var_dump( $newrow->updated_at); // NULL
$newrow->some_column = 'new data';
$newrow->save();
var_dump( $newrow->created_at ); // 2016-09-26 23:22:51 save()した日時
var_dump( $newrow->updated_at); // 2016-09-26 23:22:51
save()しないとダメなんですか?
いままでの結果からなんとなくわかりますが、replicate した時点では実体を持たないデータのようです。実際にデータベースのレコードが複製保存されるのは、save()したタイミング。
$oldrow = MyModel::find(2145);
$newrow = $oldrow->replicate();
$newrow->some_column = 'new data';
return;
// saveしない
$newrow->save();
このように、replicateしたレコードをsaveしないとデータベースのレコードは増えません。