upsertとは?
upsertとは、update + insertのことで、データの更新(update)とデータの挿入(insert)の両方の機能を併せ持っています。
upsertは、対象のレコードがあればそのレコードを更新し、レコードがなければレコードの新規追加をするという場合に便利な機能なのです。
upsertを使う場面
上記で説明した通り、対象のレコードがあれば更新して、なければ新規追加を行いときにupsertが使用できます。
例えば、データを追加する時には、新規追加画面などがなく、編集画面からデータの新規追加も更新も併せて行う場合などです。
upsertを使わない処理では、
- まずselect文で対象のデータがあるかを探す
- 対象データが見つかった場合は、updateをして情報を更新する
- 対象データが見つからなかった場合は、insertで新しくレコードを追加する
このように、1で対象のデータを探した後に、if文を使って2、3の処理を分岐させていくことになります。
ちょっと面倒だし、場合によっては結構長くなりそうですね。
このような時にupsertを使うとスッキリと書くことができます!
Laravelでupsertをしてみよう!
Laravelでupsertを使用するには
- Eloquentで、updateOrCreateを使用する方法
- クエリビルダで、updateOrInsertを使用する方法
の方法があります。
次項でそれぞれについて詳しく見ていきましょう!
EloquentのupdateOrCreateを使用する
使い方
Laravelの公式日本語ドキュメントやLaravel APIドキュメントを確認しながら、使い方を確認していきましょう!
使い方の例
こちらは、Laravel APIドキュメントに記載のある使い方です。
Model|Builder updateOrCreate(array $attributes, array $values = [])
使用例
以下のように、ユーザIDが1001のユーザを検索し、見つかった場合は、名前を’Takeru’へ、歳を33にupdateします。
もしユーザが見つからない場合は、名前を’Takeru’へ、歳を33のユーザが新規に作成されます。
User::updateOrCreate(
['user_id' => 1001],
['name' => 'Takeru', 'age' => 33]
);
ちなみに、$attributesや$valuesを複数指定したい場合も連想配列へ追加するだけです。
こちらは、検索値が複数の場合の例です。
ユーザIDが1001かつメールアドレスがtest@test.comユーザを検索し、見つかった場合は、名前を’Takeru’へ、歳を33にupdateします。
もしユーザが見つからない場合は、名前を’Takeru’へ、歳を33のユーザが新規に作成されます。
User::updateOrCreate(
['user_id' => 1001, 'email' => 'test@test.com'],
['name' => 'Takeru', 'age' => 33]
);
ソースを見てみよう!
こちらはLaravelのソースコードです。
$attributesで指定した要素で検索し、fillメソッドを用いて、upsertをしていることがわかりますね!
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php
/**
* Create or update a record matching the attributes, and fill it with values.
*
* @param array $attributes
* @param array $values
* @return \Illuminate\Database\Eloquent\Model|static
*/
public function updateOrCreate(array $attributes, array $values = [])
{
return tap($this->firstOrNew($attributes), function ($instance) use ($values) {
$instance->fill($values)->save();
});
}
fillについてはこの記事が詳しく解説されていました。
クエリビルダのupdateOrInsertを使用する
使い方
Laravelの公式日本語ドキュメントやLaravel APIドキュメントを確認しながら、使い方を確認していきましょう!
使い方の例
こちらも、Laravel APIドキュメントに記載のある使い方です。
bool updateOrInsert(array $attributes, array $values = [])
使用例
こちらは、Eloquentで示した例と同様に、ユーザIDが1001かつメールアドレスがtest@test.comユーザを検索し、見つかった場合は、名前を’Takeru’へ、歳を33にupdateします。
もしユーザが見つからない場合は、名前を’Takeru’へ、歳を33のユーザが新規に作成されます。
DB::table('users')
->updateOrInsert(
['user_id' => 1001, 'email' => 'test@test.com'],
['name' => 'Takeru', 'age' => 33]
);
ソースを見てみよう!
こちらがLaravelのクエリビルダのソースコードです。
こちらは、$attributesで指定した値によってソースコード内でもif文で条件分岐していることがわかりますね!
vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php
/**
* Insert or update a record matching the attributes, and fill it with values.
*
* @param array $attributes
* @param array $values
* @return bool
*/
public function updateOrInsert(array $attributes, array $values = [])
{
if (! $this->where($attributes)->exists()) {
return $this->insert(array_merge($attributes, $values));
}
return (bool) $this->take(1)->update($values);
}
まとめ
いかがでしたでしょうか?
Laravelでupsertする方法は理解できましたか?
システム開発では、度々upsertが使えるような場面に出会うと思います。
if文で条件分岐することでupdateとinsertの処理をそれぞれ自分で書くことはできますが、冗長になりやすいですし、Laravelではこのupsertの機能を使用できるため積極的に使用していきましょう!
コメント