web-dev-qa-db-ja.com

Laravel:DB :: transaction()でtry ... catchを使用する

複数の挿入クエリには、すべてDB::transaction()を使用します。その際、try...catchをその中に配置するか、それをラップする必要がありますか?何か問題が発生した場合にトランザクションが自動的に失敗する場合、try...catchを含める必要さえありますか?

サンプルtry...catchトランザクションのラッピング:

// try...catch
try {
    // Transaction
    $exception = DB::transaction(function() {

        // Do your SQL here

    });

    if(is_null($exception)) {
        return true;
    } else {
        throw new Exception;
    }

}
catch(Exception $e) {
    return false;
}

反対に、try ... catchをラップするDB::transaction()

// Transaction
$exception = DB::transaction(function() {
    // try...catch
    try {

        // Do your SQL here

    }
    catch(Exception $e) {
        return $e;
    }

});

return is_null($exception) ? true : false;

または、単にtry ... catchなしのトランザクション

// Transaction only
$exception = DB::transaction(function() {

    // Do your SQL here

});

return is_null($exception) ? true : false;
57
enchance

手動でコードを介してトランザクションを「終了」する必要がある場合(例外を介するか、単にエラー状態を確認する)、DB::transaction()を使用するのではなく、コードをDB::beginTransactionおよびDB::commit/DB::rollback()

DB::beginTransaction();

try {
    DB::insert(...);
    DB::insert(...);
    DB::insert(...);

    DB::commit();
    // all good
} catch (\Exception $e) {
    DB::rollback();
    // something went wrong
}

トランザクションドキュメント を参照してください。

132
alexrussell

PHP7を使用する場合は、catchThrowable を使用して、ユーザー例外と致命的なエラーをキャッチします。

例えば:

DB::beginTransaction();

try {
    DB::insert(...);    
    DB::commit();
} catch (\Throwable $e) {
    DB::rollback();
    throw $e;
}

コードをPHP5に対応させる必要がある場合は、ExceptionおよびThrowableを使用します。

DB::beginTransaction();

try {
    DB::insert(...);    
    DB::commit();
} catch (\Exception $e) {
    DB::rollback();
    throw $e;
} catch (\Throwable $e) {
    DB::rollback();
    throw $e;
}
17
mnv

トランザクションをtry..catchでラップすることも、逆にすることもできます。ここでは、Illuminate\Database\ConnectionDB:transaction()の内部を深く見ると、laravel 5で使用したサンプルコードを使用できます。手動トランザクションを書くのと同じように、

Laravel Transaction

public function transaction(Closure $callback)
    {
        $this->beginTransaction();

        try {
            $result = $callback($this);

            $this->commit();
        }

        catch (Exception $e) {
            $this->rollBack();

            throw $e;
        } catch (Throwable $e) {
            $this->rollBack();

            throw $e;
        }

        return $result;
    }

そのため、このようなコードを記述し、フラッシュ経由でメッセージをフォームに戻す、または別のページにリダイレクトするなどの例外を処理できます。クロージャ内のREMEMBERリターンはtransaction()で返されるため、redirect()->back()を返す場合、トランザクションを処理する変数で返されるため、すぐにはリダイレクトされません。

トランザクションをラップ

$result = DB::transaction(function () use ($request, $message) {
   try{

      // execute query 1
      // execute query 2
      // ..

      return redirect(route('account.article'));

   } catch (\Exception $e) {
       return redirect()->back()
          ->withErrors(['error' => $e->getMessage());
    }
 });

// redirect the page
return $result;

代わりにブール変数をスローし、トランザクション関数の外部でリダイレクトを処理するか、トランザクションが失敗した理由を取得する必要がある場合は、$e->getMessage() inside catch(Exception $e){...}から取得できます

8