Laravelでupsertする方法

Laravel

upsertとは?

upsertとは、update + insertのことで、データの更新(update)とデータの挿入(insert)の両方の機能を併せ持っています。

upsertは、対象のレコードがあればそのレコードを更新し、レコードがなければレコードの新規追加をするという場合に便利な機能なのです。

upsertを使う場面

上記で説明した通り、対象のレコードがあれば更新して、なければ新規追加を行いときにupsertが使用できます。

例えば、データを追加する時には、新規追加画面などがなく、編集画面からデータの新規追加も更新も併せて行う場合などです。

upsertを使わない処理では、

  1. まずselect文で対象のデータがあるかを探す
  2. 対象データが見つかった場合は、updateをして情報を更新する
  3. 対象データが見つからなかった場合は、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の機能を使用できるため積極的に使用していきましょう!

オススメの関連商品

コメント