91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Yii2中事務如何實現

發布時間:2021-08-27 14:01:27 來源:億速云 閱讀:125 作者:小新 欄目:開發技術

這篇文章將為大家詳細講解有關Yii2中事務如何實現,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

準備

數據庫引擎為innodb

本文使用的yii版本為2.0.5,只要是2.0以上就沒有問題

運行環境為PHP7.0.0,Mysql5.6

Yii中的事務

處理異常

/**
* 測試事務
*/
public function actionTest(){
//創建事務
$tr = Yii::$app->db->beginTransaction();
try {
for($i=1;$i<=3;$i++){
$test = new Areas();
$test->name = 'name'.$i;
$test->sort=1;
if($test->save()){
echo "save $i | ";
}
}
$test = new Areas();
$test->name = 'ab'.$i;
$test->sorta=1; //寫入不存在的字段
if(!$test->save()){
"save fail"; //如果沒有寫入就輸出
}
//提交
$tr->commit();
} catch (Exception $e) {
//回滾
$tr->rollBack();
echo "rollback";
}
}

運行結果

save 1 | save 2 | save 3 | rollback

注意,因為最后的數據沒有插入成功,觸發了事務的回滾,所以數據表沒有新增數據產生。

觸發事務回滾的原因是代碼出現了異常(Exception)。

處理數據失敗

一般來講,我們的運行中的代碼是不會出現這種明顯的異常,這種異常會在開發測試過程中消滅掉。

而真正造成數據需要回滾的是我們的某個業務出現問題,導致沒有寫入部分的數據。

/**
* 測試事務
*/
public function actionTest(){
//創建事務
$tr = Yii::$app->db->beginTransaction();
try {
for($i=1;$i<=3;$i++){
$test = new Areas();
$test->name = 'name'.$i;
$test->sort=1;
if($test->save()){
echo "save $i | ";
}
}
$test = new Areas();
$test->name = null; //數據庫設計name不能為空,人為造成寫入失敗。
$test->sort=1; //寫入不存在的字段
if(!$test->save()){
echo "save fail"; //如果沒有寫入就輸出
}
//提交
$tr->commit();
} catch (Exception $e) {
//回滾
$tr->rollBack();
echo "rollback";
}
}

運行結果如下,數據庫插入了三條數據。

save 1 | save 2 | save 3 | save fail

也就是說,如果因為業務邏輯導致某個數據表沒有寫入數據,也沒有出現對應的回滾。

改進方案如下

/**
* 測試事務
*/
public function actionTest(){
//創建事務
$tr = Yii::$app->db->beginTransaction();
try {
for($i=1;$i<=3;$i++){
$test = new Areas();
$test->name = 'name'.$i;
$test->sort=1;
if($test->save()){
echo "save $i | ";
}
}
$test = new Areas();
$test->name = null; //數據庫設計name不能為空,人為造成寫入失敗。
$test->sort=1; //寫入不存在的字段
if(!$test->save()){
throw new \yii\db\Exception(); //手動拋出異常,再由下面捕獲。
}
//提交
$tr->commit();
} catch (Exception $e) {
//回滾
$tr->rollBack();
echo "rollback";
}
}

運行結果如下,數據庫沒有插入新數據,事務被回滾。

save 1 | save 2 | save 3 | rollback

分散的數據處理

由于實際項目的復雜程度,導致我們的數據庫操作分散在不同的Model中。

所以,實際項目的代碼不會是上面的樣子。

模擬需求

接收參數:

名字

性別

簽名

業務處理流程:

接收參數

由發號器得到用戶的uid,發號器對應數據表增加一位數字

把名字、性別、簽名和上一步的uid寫入用戶信息表

初始化用戶余額表

回滾觸發時機:

初始化余額表沒有傳入uid導出沒有寫入數據

實際代碼

//Controller
/**
* 測試事務-注冊用戶
*/
public function actionReg()
{
//獲取請求
$request = Yii::$app->request;
//設定返回格式
$response = Yii::$app->response;
$response->format = \yii\web\Response::FORMAT_JSON; //返回json
//測試代碼,去掉驗證身份步驟
$name = $request->get("name");
$gender = $request->get("gender");
$sign = $request->get("sign");
//測試代碼,省略參數校驗步驟
$tr = Yii::$app->db->beginTransaction();
try {
//得到uid
$uid = App::getSeNo();
UserProfile::add($uid, $name, $gender, 1, $sign);
$user_balance = UserBalance::initUserBalance($uid);
$tr->commit(); //提交數據
} catch (Exception $e) {
//回滾
$tr->rollBack();
return $e->getMessage(); //返回自定義異常信息
}
return $user_balance;
}
//UserProfile
/**
* 添加用戶信息
* @param $user_id
* @param $nikename
* @param $gender
* @param $user_type
* @param string $intro
* @return UserProfile
* @throws \Exception
*/
public static function add($user_id, $nikename, $gender,$user_type,$intro="") {
$model = new UserProfile();
$model->gender = $gender;
$model->nikename = $nikename;
$model->user_id = $user_id;
$model->user_type=$user_type;
$model->intro=$intro;
$model->update_time = time();
$insert =$model->insert();
if(!$insert){
throw new Exception("沒有寫入用戶資料");
}
return $model;
}
//UserBalance
/**
* 初始化用戶的可提現余額
* @param $user_id
*/
public static function initUserBalance($user_id){
$info=self::find()->where(['user_id'=>$user_id])->one();
if(!$info ){
$model=new UserBalance();
$model->user_id = $user_id;
$model->price= "0";
$model->update_time=time();
$insert = $model->insert();
if(!$insert){
throw new Exception("沒有初始化用戶余額");
}
$info=$model;
}
return $info->attributes;
}

正常的結果如下

{"id":124,"user_id":1473179883,"price":"0","update_time":1473179883}

如果把初始化用戶余額部分的user_id沒有傳遞成功,返回的結果如下

"沒有初始化用戶余額"

我們可以針對具體情況定位到錯誤所在位置,及時修改。

事務(Transaction)

從上面的實際代碼可以看出,創建了事務,只要在范圍內,就算是引入的別的Model也能把異常NG返回,完成回滾操作。

一般情況下,整個Yii應用使用了同一個數據庫連接,或者說是使用了單例。

而在yii\db\Connection中,又對事務對象進行了緩存:

class Connection extends Component
{
// 保存當前連接的有效Transaction對象
private $_transaction;
// 已經緩存有事務對象,且事務對象有效,則返回該事務對象
// 否則返回null
public function getTransaction()
{
return $this->_transaction && $this->_transaction->getIsActive() ? $this->_transaction : null;
}
// 看看啟用事務時,是如何使用事務對象的
public function beginTransaction($isolationLevel = null)
{
$this->open();
// 緩存的事務對象有效,則使用緩存中的事務對象
// 否則創建一個新的事務對象
if (($transaction = $this->getTransaction()) === null) {
$transaction = $this->_transaction = new Transaction(['db' => $this]);
}
$transaction->begin($isolationLevel);
return $transaction;
}
}

關于“Yii2中事務如何實現”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

绥中县| 连城县| 荔浦县| 美姑县| 赞皇县| 福建省| 栖霞市| 舒兰市| 贡嘎县| 平舆县| 衡山县| 新昌县| 贡山| 黄石市| 遂川县| 彰化县| 广宁县| 元江| 德钦县| 辽宁省| 连州市| 沁源县| 平潭县| 西昌市| 临夏市| 墨脱县| 维西| 永宁县| 肃北| 元氏县| 上高县| 延吉市| 高州市| 德清县| 德惠市| 区。| 龙川县| 双柏县| 湘潭县| 四平市| 赫章县|