[PHP]Yii2框架的坑

Yii2框架的幾個隱蔽的坑


摘要:Yii2是一款優秀的通用Web後端框架,結構簡單優雅、實用功能豐富、擴展性強、性能搞是他最突出的優勢。它優秀的地方你在使用過程當中總能輕易的發現,無須贅述。而這些隱蔽的小瑕疵,顯得更有必要告訴你們。php



目錄

說點閒話

距離上次寫博客,已經有三個月了。在動手寫以前,老是帶着深深的罪惡感。被它折磨許久,終於,仍是,動手了。css

值得慶祝的一件事:最近開始,天天早上8:30起來健身了。有兩個視頻很好用,只需8分鐘,照着作一遍保證你(生)爽(不)到(如)爆(死)。(8分鐘腹肌鍛鍊第2級-下載8分鐘胸肌鍛鍊第2級-下載html

值得反思的一件事:最近看了《叔本華美學隨筆》,改變了我一直以來對閱讀的見解。我曾經覺得閱讀是進步的源動力,卻被這本書深深的打臉了。來,先給你們分享一段:git

咱們只管所見的外在環境並不像閱讀物那樣,把某已肯定的看法強加給咱們的頭腦,而只是爲咱們提供了素材和機會。去思考與咱們的頭腦能力相稱、與當下的情緒相符的事情。因此,太多的閱讀會是咱們的精神失去彈性,就像把一重物持續壓在一條彈簧上面就會是彈簧失去彈性同樣;而讓本身沒有本身思想的最穩妥的辦法就是在空閒的每一分鐘立刻隨手拿起一本書。github

思考纔是進步的源動力web

好了,扯淡完畢,步入正題。數據庫

ActiveRecord被莫名寫入?

準備知識

  1. 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();              //保存,會發現此行的其它字段都被寫成默認值了。

總結問題

這個例子的問題在於:canvas

  1. 我從數據庫中取出了一行,也就是代碼中的$room,可是隻取出了id字段,而其餘字段天然就是默認值。
  2. 當我$room->save()的時候,那些是默認值的字段也被保存到數據庫裏去了。what!?
  3. 也就是說,當你想節約資源,不取出全部字段的時候,必定要注意不能保存,不然,不少數據會被莫名修改成默認值。

解決方法

然而,咱們有什麼解決辦法呢?提供幾種思路:後端

  1. 本身時刻注意,避免未徹底取出的ActiveRecord的保存。
  2. 修改或繼承ActiveRecord, 使得,當此對象由find()新建,且字段沒有徹底取出,調用save()方法,拋出異常。
  3. 修改或繼承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();
}

問題總結

這段代碼的問題在於:yii2

  1. 你們知道$transaction的存在乎義是保證整段數據庫存儲代碼要麼全成功,要麼全失敗。
  2. 顯然,在這個例子中,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,世界就清淨了。因此,若是你遇到這種問題,感激我吧。

相關文章
相關標籤/搜索