レコードのコピーという作業は結構起こることです。例えば、Eコーマースのサイトなら、サイズだけが違う商品は、説明などの他の属性はほとんど同じなので、わざわざ新規の商品の情報をすべて手入力というよりは、既存の商品をもとに編集する方がもちろん簡単です。

さて、このレコードのコピー作業、Eloquentではどうやるのでしょう?

tinkerを立ち上げます。

まず、usersのテーブルを空にしましょう。

Psy Shell v0.9.9 (PHP 7.1.14 — cli) by Justin Hileman
>>> User::truncate();
=> Illuminate\Database\Eloquent\Builder {#2862}
>>> User::count();
=> 0

次に、ファクトリーを利用してレコードを1つ作成します。

>>> factory(App\User::class, 1)->create();
=> Illuminate\Database\Eloquent\Collection {#2896
     all: [
       App\User {#2892
         name: "Yessenia Jast",
         email: "modesto24@example.org",
         updated_at: "2019-01-06 05:13:54",
         created_at: "2019-01-06 05:13:54",
         id: 1,
       },
     ],
   }
>>> 

そして、このレコードをcloneして保存。

>>> $user = User::find(1);
=> App\User {#121
     id: 1,
     name: "Yessenia Jast",
     email: "modesto24@example.org",
     created_at: "2019-01-06 05:13:54",
     updated_at: "2019-01-06 05:13:54",
   }
>>> $clone = clone $user;
=> App\User {#2894
     id: 1,
     name: "Yessenia Jast",
     email: "modesto24@example.org",
     created_at: "2019-01-06 05:13:54",
     updated_at: "2019-01-06 05:13:54",
   }
>>> $clone->save();
=> true
>>> User::count();
=> 1
>>> 

あれれ、新規のレコードを作成してくれませんね。レコード数はオリジナルのレコードの1個です。$cloneは単に同じDBレコードを違うオブジェクトとしただけなので、$clone->save()は新規登録ではなく既存のレコードの編集となってしまうようです。

正しいやり方は、Eloquentのreplicate()を使用してコピーのオブジェクトを作成します。

>>> $clone = $user->replicate();
=> App\User {#2862
     name: "Yessenia Jast",
     email: "modesto24@example.org",
   }
>>> $clone->email = 'test@example.com';
=> "test@example.com"
>>> $clone->save();
=> true

emailはユニークな値でないとDBの重複エラーとなるので違う値にしてsaveしていることに注意してください。

以下のように、レコードは2つになり、複製が作成されています。

>>> User::all();
=> Illuminate\Database\Eloquent\Collection {#2863
     all: [
       App\User {#2888
         id: 1,
         name: "Yessenia Jast",
         email: "modesto24@example.org",
         created_at: "2019-01-06 05:13:54",
         updated_at: "2019-01-06 05:13:54",
       },
       App\User {#2893
         id: 2,
         name: "Yessenia Jast",
         email: "test@example.com",
         created_at: "2019-01-06 05:16:06",
         updated_at: "2019-01-06 05:16:06",
       },
     ],
   }

By khino