#phalapi-進階篇4(notrom進階以及事務操作)#

##前言##
***先在這里感謝phalapi框架創始人@dogstar為我們提供了這樣一個優秀的開源框架。***
寫本篇教程的起因是因為在交流的時候有位童鞋提出了fetchPairs有BUG,之前一直沒有仔細了解過notorm的細節,借此機會把notorm中的一些方便快捷的操作,以及notorm中有關事務的操作和使用,具體地作一下分析。
附上:
喵了個咪的博客:[w-blog.cn](w-blog.cn)
官網地址:[http://www.phalapi.net/](http://www.phalapi.net/ "PhalApi官網")
開源中國Git地址:[http://git.oschina.net/dogstar/PhalApi/tree/release](http://git.oschina.net/dogstar/PhalApi/tree/release "開源中國Git地址")
##1. 進一步了解notorm##
notorm中很多操作在PhalApi官方文檔中并沒有非常詳細的介紹,這里把一些常用到的notorm函數作一下相關的介紹。
###1.1 fetchPairs###
fetchPairs的使用和fetchAll相似但不盡相同,fetchPairs需要傳遞一個參數,這個參數是字符串類型的key值(比如:name 、id),當參數傳遞之后會出現這樣的對比效果:
DI()->notorm->user->fetchPairs('name');

DI()->notorm->user->fetchAll('name');

大家有看到區別嗎?
嗯!是fetchPairs在返回的時候把在之前定義的key值放到了返回數組的key中。
**提示:在老版本中,使用過程中 Result.php 會有一句 821行的報錯,需要把**
$values = array_values(iterator_to_array($row));
改成
$values = array_values($row);
###1.2 lock ###
lock操作是一種鎖的行為,對整表進行鎖定,在當前用戶釋放鎖之前此表不能再被操作。lock接受一個bool參數,默認是true,即鎖表,使用如下:
$userdb = DI()->notorm->user->lock(); //鎖定表
$rs = $userdb->fetchAll();
生成的sql語句如下:
SELECT * FROM user FOR UPDATE;
###1.3 加操作###
在很多時候,我們會遇到數據庫表里面的某個值需要+1操作,我們不能簡單地在update的時候寫入array('key' => 'key+1'),因為在解析sql的時候,key+1 會帶上引號作為一個字符串被處理,所以,這樣的操作并沒有達到我們想要的效果,當然,這是有解決方法的。具體操作如下:
DI()->notorm->user->where('id', 1)->update(array('sum' => new NotORM_Literal("sum + 1")));
這樣就可以生成不帶引號的操作了:
UPDATE user SET phone = sum + 1 WHERE (id = 1);
###1.4 group ###
group是去重操作,在notorm里面也有封裝,我們可以使用group來統計比如有多少同名的用戶等一些統計操作,或者是找出庫里面不重復的城市名等。
DI()->notorm->user->select('name , count(*) as count')->group('name')->fetchAll();
會獲得如下結果

###1.5 快速函數sum,count,max,min ###
在我們使用notorm快速函數的過程中,雖然此類函數使用頻率不高,但是使用起來卻是很方便:
return DI()->notorm->user->sum('id'); //做加法
return DI()->notorm->user->max('id'); //獲取這個key中最大的值
return DI()->notorm->user->min('id'); //獲取這個key中最小的值
return DI()->notorm->user->count(); //統計一共幾條數據
##2. 事務操作##
其實,很大一部分使用事務的原因是因為害怕在并發的情況下導致對數據庫造成的重復操作,比如如下場景:
兩個管理者對同一應用進行審核。他們同一時間查詢到應用的狀態都是未審核,然后都進行了審核操作,這時,返回的審核操作狀態是成功的。但這時,會有一個管理者會發現審核狀態和自己的審核結果不同,這就有問題了。大部分在解決此類問題時,都會考慮使用數據庫的事務操作。其實,對于事務操作,我的建議是:能不用盡量不用。我簡單聊一下我的幾個觀點:
1. 是否真的那么重要?對于上面的問題,也許乍一看覺得:這怎么可能呢?但是仔細一想,這兩個操作都是屬于兩個管理者的正常操作。對于業務來說,我認為是沒有問題的。當然這是因為影響不大;如果是付款,一個訂單從兩個地方同時付款,然后都發現是未付款,然后都進行了付款,這種業務就必須有處理方式了,所以是否使用事務要看業務是否非常重要。
2. 概率是怎么樣的?對于一個程序來說,兩個請求剛好通過了查詢過程,并一同到了修改的操作,不管是什么場景,發生這種并發沖突的可能性是極其微小的,我覺得幾乎可以忽略(當然前提是重要性沒有那么的高,我們不能 **以偏概全** )。
3. **曲線救國**,其實,我們可以使用其他方式避免這類問題。我們可以把我們需要驗證條件加入到Update的條件中,這樣兩條語句終歸會有一條語句執行失敗。
notorm中使用到的事務操作方式:
notorm提供了常規的事務操作如下:
//第一步:先指定待進行事務的數據庫(通過獲取一個notorm表實例來指定;否則會提示:PDO There is no active transaction)
$user = DI()->notorm->user;
//第二步:開啟事務開關(此開關會將當前全部打開的數據庫都進行此設置)
DI()->notorm->transaction = 'BEGIN';
//第三步:進行數據庫操作
$user->insert(array('name' => 'test3',));
$user->insert(array('name' => 'test4',));
//第四:提交/回滾
DI()->notorm->transaction = 'COMMIT';
//DI()->notorm->transaction = 'ROLLBACK';
還有一種處理方式就是在操作之前進行lock鎖表
$user = DI()->notorm->user;
$user->lock();
$user->insert(array('name' => 'test3',));
$user->insert(array('name' => 'test4',));
這兩種方式大家可以自行取舍。
注:在phalapiV1.31版本后有自帶提供事務操作可參考文檔。
##3. 總結##
在本小節中,對于notorm中的一些特別的封裝函數進行了介紹,對于事務提出了自己的看法和觀點以及使用notorm的解決方案。希望看了這篇教程的童鞋,在日常開發中對你有所幫助。
注:筆者能力有限,有說的不對的地方,希望大家能夠指出,也希望多多交流!
**官網QQ交流群:421032344 歡迎大家的加入!**
####[上一章](/wikis/%5b7.9%5d-phalapi-%e8%bf%9b%e9%98%b6%e7%af%873(%e8%87%aa%e5%8a%a8%e5%8a%a0%e8%bd%bd%e5%92%8c%e6%8b%a6%e6%88%aa%e5%99%a8).html) [文檔首頁](/wikis/) [下一章](/wikis/%5b7.11%5d-phalapi-%e8%bf%9b%e9%98%b6%e7%af%875(%e6%95%b0%e6%8d%ae%e5%ba%93%e8%af%bb%e5%86%99%e5%88%86%e7%a6%bb).html)
- 空白目錄
- [7.1]-phalapi-入門篇1(簡單介紹以及環境搭建)
- [7.2]-phalapi-入門篇2(把它玩起來)
- [7.3]-phalapi-入門篇3(請求和返回)
- [7.4]-phalapi-入門篇4(國際化高可用和自動生成文檔)
- [7.5]-phalapi-入門篇5(數據庫操作和Model層)
- [7.6]-phalapi-入門篇6(小技巧和淺談API適用范圍以及入門篇總結)
- [7.7]-phalapi-進階篇1(三層結構Api,Domain,和Model)
- [7.8]-phalapi-進階篇2(DI依賴注入和單例模式)
- [7.9]-phalapi-進階篇3(自動加載和攔截器)
- [7.10]-phalapi-進階篇4(notorm進階以及事務操作)
- [7.11]-phalapi-進階篇5(數據庫讀寫分離)
- [7.12]-phalapi-進階篇6(解決大量數據存儲數據庫分表分庫拓展)
- [7.13]-phalapi-進階篇7(使用緩存以及用redis拓展解決實際問題)
- [7.14]-phalapi-進階篇8(PhalApi能帶來什么和進階篇總結)