Laravelの、firstOrCreateとfirstOrNewの違いを調べました。
でも、まさしく、名前のままでした。
念のため、詳細は、
https://laravel.com/docs/5.1/eloquent
firstOrCreateは、実行時にレコードを作成
その名の通り、firstか、create。
実行時に、指定したパラメータを持ったレコードが無ければ、createします。
(外部キー制約がある場合、外部キーも渡さないとcreate時にexceptionになります)
// Eloquentを継承したAreaクラスがあったとする
$area = Area::firstOrCreate(['name' => '北海道']);
// wasRecentlyCreated を用いることで、今回のリクエストで作成されたことを判定できる
if ($area->wasRecentlyCreated) {
// 既にcreateされているので、idなどのattributeにもアクセスできる
}
firstOrNewは、インスタンスを作成するだけ
newするだけなので、まだレコードとして記録されていません。
いい感じに処理したあとは、save()
しましょう。DBにレコードが記録されます。
(レコードに外部キー制約がある場合、saveするより前に外部キーをつけてあげればOK。便利です。)
// Eloquentを継承したAreaクラスがあったとする
$area = Area::firstOrNew(['name' => '北海道']);
if (!$area->exists) {
// レコードが存在しないときは、existsがfalseになる
// まだcreateされていないため、idなどのattributeにはアクセス出来ない
...
...
// saveすることでcreateできる
$area->save();
}
if ($area->wasRecentlyCreated) {
// saveによって、新しくレコードが作られたことを判定できる
...
}
createされたかどうかの判定の仕方
wasRecentlyCreated
で判定することができます!
newされたものかどうかの判定の仕方
exists
というプロパティが使えそうです(Laravel5.1のModel実装)。
これは、レコードが存在するかどうかを示すbool値です。このことから、firstOrNew
の直後に、そのインスタンスがfirstで取れたものか、newされたものかをチェックする必要があるときには、使いやすいプロパティかなと感じます。
Laravel 5.1 未満の create, new判定
Lravel 5.1未満では、wasRecentlyCreatedは使用できませんでした。
そのため、私は以下のような方法で実装していました。
// Eloquentを継承したAreaクラスがあったとする
$area = Area::firstOrNew(['name' => '北海道']);
if (!$area->id) {
// saveすることでcreateできる
$area->save();
}
firstOrNewを使用して、取得したインスタンスにidが付与されているかどうかを確認することで、新規追加のデータかどうかを調べられます。しかし、Laravel 4.2でもexists
のプロパティがありました。こちらのほうが意図が伝わりやすい書き方になりそうです。
firstOrCreateの方では、おそらくレコードの新規追加をチェックできなさそうです。Createしてしまうと、idも付与されてしまいますので。idでできないとするならば、空のカラムあるなどのチェックとかなら、できそうですね。