우리는 모두 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;
}
반대로 DB::transaction()
try … catch :
// 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;
답변
코드를 통해 트랜잭션을 수동으로 ‘종료’해야하는 경우 (예외를 통하거나 단순히 오류 상태를 확인하는 경우) 사용해서는 안되며 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
}
트랜잭션 문서를 참조하십시오 .
답변
PHP7을 사용하는 경우 사용자 예외 및 치명적인 오류를 포착 하기 위해 Throwable in catch
을 사용하십시오 .
예를 들면 :
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;
}
답변
당신이 깊은 내부를 보면 당신은 ,, 여기, 내가 laravel 5에 사용되는 내 예제 코드를 리버스도시켜 try..catch를 통해 거래를 포장 또는 수 DB:transaction()
의 Illuminate\Database\Connection
당신처럼 같은 수동 트랜잭션을 작성하는 것이 있습니다.
라 라벨 거래
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 return inside Closure는 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()
내부 에서 가져올 수 있습니다.catch(Exception $e){...}
답변
복잡한 try-catch 블록보다 더 간단한 구문을 사용하여 해결할 수 있다고 생각하기 때문에이 질문에 대한 답을 제공하기로 결정했습니다. Laravel 문서는이 주제에 대해 매우 간단합니다.
try-catch를 사용하는 대신 DB::transaction(){...}
다음과 같은 래퍼를 사용할 수 있습니다 .
// MyController.php
public function store(Request $request) {
return DB::transaction(function() use ($request) {
$user = User::create([
'username' => $request->post('username')
]);
// Add some sort of "log" record for the sake of transaction:
$log = Log::create([
'message' => 'User Foobar created'
]);
// Lets add some custom validation that will prohibit the transaction:
if($user->id > 1) {
throw AnyException('Please rollback this transaction');
}
return response()->json(['message' => 'User saved!']);
});
};
그러면 사용자와 로그 레코드가 서로 없이는 존재할 수 없음을 확인해야합니다.
위의 구현에 대한 몇 가지 참고 사항 :
- 콜백 내에서 반환을
return
사용할 수 있도록 트랜잭션 을 확인하십시오response()
. throw
트랜잭션을 롤백하려면 예외 를 확인하십시오 (또는 Eloquent 내의 SQL 예외와 같이 자동으로 예외를 발생시키는 중첩 함수가 있음).- 는
id
,updated_at
,created_at
및 기타 필드는 사용할 수 AFTER 생성됩니다$user
(이 트랜잭션 (transaction)의 기간) 객체입니다. 트랜잭션은 보유한 모든 생성 로직을 통해 실행됩니다. 그러나를AnyException
던지면 전체 레코드가 삭제됩니다 . 이것은 예를 들어 자동 증가 열id
이 실패한 트랜잭션에서 증가한다는 것을 의미 합니다.
Laravel 5.8에서 테스트 됨