>  기사  >  백엔드 개발  >  Yii2 개발: 클로저와 유사한 방식으로 트랜잭션을 캡슐화하는 방법

Yii2 개발: 클로저와 유사한 방식으로 트랜잭션을 캡슐화하는 방법

不言
不言원래의
2018-08-14 10:41:131361검색

이 글의 내용은 Yii2 개발에 관한 것입니다. 클로저와 같은 방식으로 트랜잭션을 캡슐화하는 방법입니다. 필요한 친구들이 참고할 수 있기를 바랍니다.

컨트롤러에서 트랜잭션을 실행할 때 일반적인 코드는 다음과 같습니다.

$transaction = Yii::$app->db->beginTransaction();
try {
    //一些业务代码
    $transaction->commit();
} catch (\Exception $e) {
    $transaction->rollBack();
    throw $e;
}

그래서 이 코드 구조는 // 일부 비즈니스 코드 부분만 다를 뿐이지 여러 번 반복해야 한다고 생각했습니다. 별로 중복되지 않나요? 그리고 안돼! 좋은! 바라보다! , 그래서 해결책을 찾으려고 노력했습니다. 처음에는 stackflow에서 비슷한 질문을 찾았습니다. 이를 모델에 캡슐화하는 방법이 있지만 그렇게 하려면 중첩된 트랜잭션과 같은 특정 문제가 있습니다. Q&A를 보려면 여기를 클릭하세요.

우리 Yii 프레임워크는 메소드 트랜잭션을 제공합니다. 얼핏 보면 매개변수 전달 문제를 해결할 수 없는 것처럼 보입니다. 지금은 무시해 보겠습니다. 아래에서 메소드는 다음과 같이 호출됩니다. 이 메소드의 소스 코드

Yii::$app->db->transaction(function() {
    //一些业务代码
});

이 메소드는 콜백 함수와 트랜잭션의 격리 수준을 허용합니다.

여기에서 이 메소드가 중복 코드를 해결하지만 여전히 해결되지 않은 몇 가지 문제가 있음을 알 수 있습니다. , 외부 처리를 수신할 때 이 메서드에서 throw된 예외를 사용해야 합니다. 이는 클라이언트에게 매우 불리합니다.

둘째: 로깅을 하지 않으면 문제가 발생하더라도 제거가 쉽지 않습니다.
세 번째: 사실 여전히 첫 번째 질문입니다. 각 예외를 처리하고 트랜잭션 메서드 외부에 try...catch... 계층을 중첩해야 한다면 이를 캡슐화하지 않는 것과 다르지 않은 것 같나요?

메서드는 확장할 수 있지만 수정할 수는 없다는 원칙에 따라 자체 공용 메서드에서 이 메서드를 오버로드해야 합니다. 오버로딩 코드는 다음과 같습니다.

/**
 * Executes callback provided in a transaction.
 *
 * @param callable $callback a valid PHP callback that performs the job. Accepts connection instance as parameter.
 * @param string|null $isolationLevel The isolation level to use for this transaction.
 * See [[Transaction::begin()]] for details.
 * @throws \Exception|\Throwable if there is any exception during query. In this case the transaction will be rolled back.
 * @return mixed result of callback function
 */
public function transaction(callable $callback, $isolationLevel = null)
{
    $transaction = $this->beginTransaction($isolationLevel);
    $level = $transaction->level;

    try {
        $result = call_user_func($callback, $this);
        if ($transaction->isActive && $transaction->level === $level) {
            $transaction->commit();
        }
    } catch (\Exception $e) {
        $this->rollbackTransactionOnLevel($transaction, $level);
        throw $e;
    } catch (\Throwable $e) {
        $this->rollbackTransactionOnLevel($transaction, $level);
        throw $e;
    }

    return $result;
}
그런 다음 매개 변수를 전달하는 방법에 대한 질문으로 돌아가서 다음을 사용할 수 있습니다. 클로저를 닫고 다음과 같이 유사 코드 단락을 게시합니다.

public static function TransactionExecute(callable $function,$level=null)
{
    try{
        \Yii::$app->db->transaction($function,$level);
}catch (\Exception $e){
        //记录日志
        \Yii::error($e->getMessage());
        //这里可以理解成抛出自定义的异常类。
        (new self())->returnWayTip(1004, 'trans异常错误');
    }
}
관련 권장 사항:

php의 시스템 설정은 무엇입니까? PHP에서 일반적으로 사용되는 시스템 설정 요약(코드 포함)

php는 json을 어떻게 생성합니까? json을 생성하는 PHP의 메소드 코드

위 내용은 Yii2 개발: 클로저와 유사한 방식으로 트랜잭션을 캡슐화하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.