[PHP]Yii2架構的坑.md—/Users/zjh/Documents/我的文章/[PHP]Yii2架構的坑
Yii2架構的幾個隱形坑
摘要:Yii2是一款優秀的通用Web後端架構,結構簡單優雅、實用功能豐富、擴充性強、效能搞是他最突出的優點。它優秀的地方你在使用過程中總能輕易的發現,無須贅述。而這些隱形小瑕疵,顯得更有必要告訴大家。
- 部落格: http://www.cnblogs.com/jhzhu
- 郵箱: jhzhuustc@gmail.com
- 作者: 知明所以
- 時間: 2015-08-17
目錄
- Yii2架構的幾個隱形坑
- 目錄
- 說點閑話
- ActiveRecord被莫名寫入?
- 你的Transaction生效了嗎?
- 'Y-m-d'不被識別?
說點閑話
距離上次寫部落格,已經有三個月了。在動手寫之前,總是帶著深深的罪惡感。被它折磨許久,終於,還是,動手了。
值得慶祝的一件事:最近開始,每天早上8:30起來健身了。有兩個視頻很好用,只需8分鐘,照著做一遍保證你(生)爽(不)到(如)爆(死)。(8分鐘腹肌鍛煉第2級-下載,8分鐘胸肌鍛煉第2級-下載)
值得反思的一件事:最近看了《叔本華美學隨筆》,改變了我一直以來對閱讀的看法。我曾經以為閱讀是進步的源動力,卻被這本書深深的打臉了。來,先給大家分享一段:
我們只管所見的外在環境並不像閱讀物那樣,把某已確定的見解強加給我們的頭腦,而只是為我們提供了素材和機會。去思考與我們的頭腦能力相稱、與當下的情緒相符的事情。所以,太多的閱讀會是我們的精神失去彈性,就像把一重物持續壓在一條彈簧上面就會是彈簧失去彈性一樣;而讓自己沒有自己思想的最穩妥的辦法就是在閒置每一分鐘馬上隨手拿起一本書。
思考才是進步的源動力!
好了,扯淡完畢,步入正題。
ActiveRecord被莫名寫入?
準備知識
ActiveRecord
的基本用法。如果不理解,可參考這裡。
代碼現場
/** * @property integer $id * @property string $name * @property string $detail * @property double $price * @property integer $area **/class OcRoom extends ActivieRecord{ ...}$room = OcRoom::find() //先取出一個對象。 ->select(['id']) //只取出'id'列 ->where(['id'=>20]) ->one();$room->save(); //儲存,會發現此行的其它欄位都被寫成預設值了。
總結問題
這個例子的問題在於:
- 我從資料庫中取出了一行,也就是代碼中的
$room
,但是只取出了id
欄位,而其他欄位自然就是預設值。
- 當我
$room->save()
的時候,那些是預設值的欄位也被儲存到資料庫裡去了。what!?
- 也就是說,當你想節約資源,不取出所有欄位的時候,一定要注意不能儲存,否則,很多資料會被莫名修改為預設值。
解決方案
然而,我們有什麼解決辦法呢?提供幾種思路:
- 自己時刻注意,避免未完全取出的
ActiveRecord
的儲存。
- 修改或繼承
ActiveRecord
, 使得,當此對象由find()
建立,且欄位沒有完全取出,調用save()
方法,拋出異常。
- 修改或繼承
ActiveRecord
,使得,當此對象由find()
建立,且欄位沒有完全取出,調用save()
方法時,只儲存取出過的欄位,其他欄位被忽略。
你的Transaction生效了嗎?
代碼現場
/** * @property integer $id * @property string $name **/class OcRoom extends ActiveRecord{ public function rules() { return [['name','string','min'=>2,'max'=>10]]; } ...}class OcHouse extends ActiveRecord{ public function rules() { return [['name','string','max'=>10]]; } ...}$a = new OcRoom();$a->name = ''; //name為空白字串,不滿足rules()條件。$b = new OcHouse();$b->name = '我的房間'; //name合法,可以儲存。$transaction = Yii::$app->db->beginTransaction();try{ $a->save(); //name欄位不合法,無法驗證通過,在validate()階段已經返回false,不會進行資料庫儲存的步驟,所以也不會拋出異常。 $b->save(); //name欄位合法,可以正常儲存。 $transaction->commit(); //提交後,發現$a儲存失敗,而$b儲存成功。}catch (Exception $e) { Yii::error($e->getTraceAsString(),__METHOD__); $transaction->rollBack();}
問題總結
這段代碼的問題在於:
- 大家知道
$transaction
的存在意義是保證整段資料庫儲存代碼要麼全成功,要麼全失敗。
- 顯然,在這個例子中,
transaction
並沒有達到我們想要的效果:$a
因為validate()
都沒過,所以$transation->commit()
的時候並不會報錯。
解決方案
在$transation
塊內,所有的save()
都要判斷下傳回值,如果為false
,則直接拋出異常。
'Y-m-d'不被識別?
代碼現場
OcRenterBill extends ActiveRecord{ public function rules() { return [ ['start_time','date','format'=>'Y-m-d'], ]; }}$a = new OcRenterBill();$a = '2015-09-12';$a->save(); //會報錯,說格式不對。
問題總結
如果一開始,Yii架構就報錯,這個還不算坑。坑的是我在Mac上開發時,這個可以完全正常的工作,而發布到線上環境(Ubuntu)後,就彈出“屬性start_time格式無效”的錯誤。而參考官方文檔,發現這種格式是允許的官方文檔。
啊啊啊。各種試錯,最後發現如果改成php:Y-m-d
,世界就清淨了。所以,如果你遇到這種問題,感激我吧。
以上就介紹了[PHP]Yii2架構的坑,包括了方面的內容,希望對PHP教程有興趣的朋友有所協助。