仕事

Laravelのupsertで躓いた話

2023年5月10日

またまた仕事の話になるんだけど、Laravelのupsertのせいで結構時間を無駄にしてしまった。ムカついたので二度とこいつで躓かないようにここにメモることにする。

upsertメソッドで何ができるか必ず忘れる未来の俺に説明したいんだけど、簡単に言うとDBの値に挿入や更新をうまく切り分けてしてくれる超便利なやつ。

使い方はこんな感じ。

$saveUser = [
    "id" => $request->input("data.userId"),
    "name" => $request->input("data.name"),
    "email" => $request->input("data.email"),
];
try {
    $user = retry($retry, function () use ($saveUser) {
        return \DB::transaction(function () use ($saveUser) {
            return User::upsert(
                $saveUser,
                ['id']
            );
        });
    });
} catch (\PDOException $pdoe) {
    $response = response()->json([
        'errorId' => 'abc', 
        'errorMessage' => 'システムエラー',
        'data' => null
    ], 200);

    return $response;
}

で何に躓いてしまったかというと、upsertメソッドの第2引数に指定したカラム名がDBレベルでuniqueでもprimary keyでもなかったためエラーになった。どっちかにしないといけないらしい。


上記のLaravel公式サイトのドキュメントを直訳した文が↓

SQL Server を除くすべてのデータベースでは、upsert メソッドの 2 番目の引数の列に「プライマリ」または「一意」インデックスが必要です。 さらに、MySQL データベース ドライバーは、upsert メソッドの 2 番目の引数を無視し、常にテーブルの「プライマリ」インデックスと「一意」インデックスを使用して既存のレコードを検出します。

(引用:https://laravel.com/docs/9.x/eloquent#upserts)

-仕事