Développement Yii2 : Comment encapsuler les transactions de manière similaire à une fermeture

不言
Libérer: 2023-04-03 18:44:01
original
1416 Les gens l'ont consulté

Le contenu de cet article concerne le développement de Yii2 : Comment encapsuler les transactions de manière similaire à une fermeture. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Lors de l'exécution d'une transaction dans le contrôleur, le code général est le suivant :

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

Je pensais donc, cette structure de code, seulement // certains codes métiers sont différents, mais il doit être répété plusieurs fois. N'est-ce pas redondant ? Et non ! bien! regarder! , j'ai donc essayé de trouver une solution. Au début, j'ai trouvé une question similaire sur stackflow. Il existe une solution pour l'encapsuler dans le modèle, mais cela pose certains problèmes, comme les transactions imbriquées. pouvez cliquer ici pour voir la question.

Notre framework Yii fournit une méthode transaction. À première vue, il semble qu'il ne puisse pas résoudre le problème du passage des paramètres. Ignorons-le pour l'instant, la méthode est appelée comme suit :

Yii::$app->db->transaction(function() {
    //一些业务代码
});
Copier après la connexion

Regardons le code source de cette méthode

/**
 * 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;
}
Copier après la connexion

Cette méthode accepte une fonction de rappel et le niveau d'isolement de la transaction
De là, nous pouvons voir que bien que cela. La méthode résout le problème du code en double, il y en a encore plusieurs. Il y a deux problèmes qui n'ont pas été résolus :
Premièrement, l'exception levée par cette méthode doit être gérée en dehors de la réception. Nous ne pouvons pas la lancer directement, ce qui est très. hostile envers le client.
Deuxième : sans journalisation, même si un problème survient, il ne sera pas facile à éliminer.
Troisième : en fait, c'est toujours la première question. Si nous devons gérer chaque exception et imbriquer une couche de try...catch... en dehors de la méthode de transaction, alors cela ne semble pas être différent de ne pas encapsuler. il?

Selon le principe selon lequel les méthodes peuvent être étendues mais non modifiées, nous devons surcharger cette méthode dans notre propre méthode publique. Le code de surcharge est le suivant :

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异常错误');
    }
}
Copier après la connexion

Retournez ensuite à. comment passer les paramètres Question, nous pouvons utiliser des fermetures et poster un morceau de pseudo code, comme suit :

//执行事务
PublicFunction::TransactionExecute(function () use ($token_reward, $reward_info) {
        //业务代码
        $token_reward->save(0);
    MsgHelper::send($reward_info['post_id'], MsgHelper::SOMEONE_FINISH_REWARD, $reward_info);

    });
Copier après la connexion

Recommandations associées :

Quels sont les paramètres système en php ? Résumé des paramètres système couramment utilisés en php (avec code)

Comment php génère-t-il json ? Code de méthode pour que php génère json

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal