2011-10-06 71 views
2

我正在DB中實現訂閱。電子郵件必須是唯一的,所以我在數據庫中有一個UNIQUE索引。我有這樣的代碼在我的頁面初始化:在db中處理重複錯誤的正確方法是什麼

$f = $p->add('MVCForm'); 
$f->setModel('Account',array('name','surname','email')); 
$f->elements['Save']->setLabel('Subscribe'); 

if($f->isSubmitted()) 
{ 
    try 
    { 
     $f->update(); 

     //More useful code to execute when all is ok :) 

    } 
    catch(Exception_ValidityCheck $v) 
    { 
     //Handles validity constraint from the model 
     $f->getElement($v->getField())->displayFieldError($v->getMessage()); 
    } 
    catch(SQLException $se) 
    { 
     //If I'm here there is a problem with the db/query or a duplicate email 
    } 
} 

SQLException的唯一信息是格式化的HTML郵件,這是檢測的誤差是重複的條目的唯一途徑?

+0

請看http://fossies.org/unix/www/atk4-4.1.zip:a/atk4/lib/SQLException.php。恕我直言,我認爲你可以一般處理它們。報告錯誤已經足夠了。或者,您可以先檢查用戶電子郵件是否存在。 – Tommy

+0

在詢問這裏之前,我查看了源代碼......在重複的情況下是不夠的,我需要在另一個頁面上重定向用戶。也許SQLException可以正確設置錯誤代碼以反映數據庫錯誤或將其映射爲更多數據庫不可知的方式? –

+0

@TheElter偉大的問題。 – romaninsh

回答

1

下面是做到這一點的一種方法:

https://github.com/atk4/atk4-web/blob/master/lib/Model/ATK/User.php#L95

但如果你要對其執行重複數據刪除的自定義操作,您應該向外移動的getBy的模型,轉化爲頁面的邏輯。

+0

這是一個很好的解決方案來檢查模型中的約束。也許可以通過僅按需收集回溯數據,而不是在構造函數中,減少CPU佔用率。 –

+0

我打算分離出一些不會生成回溯的異常,但如果回溯未在構造器中捕獲,則沒有多大用處。 「Exception_StopInit」就是這樣一個不需要回溯的異常的好例子。 – romaninsh

-1

爲什麼你不想運行簡單的選擇來檢查電子郵件是否已被使用?

或使其INSERT IGNORE,然後檢查affected_rows

+0

索引的目的是爲了避免選擇,在併發情況下是處理兩個同時插入相同值的最安全的方法。 –

+0

我不會說這個索引是爲了避免選擇。那麼讓它插入IGNORE,然後檢查affected_rows,如果你不喜歡select –

+0

可能是一個好主意,但是這需要正確包裝到敏捷工具包的邏輯中,因爲你不只是拋出裸體查詢。我會試着擴展這個想法。 – romaninsh

0

由於@Col建議,我們要使用「插入忽略」。

$ form-> update()依賴於Model-> update(),然後依靠DSQL類來構建查詢。 DSQL確實爲support options,但模型會爲您生成新鮮的SQL。

Model-> dsql()爲模型構建查詢。它可以運行多個「實例」,其中每個實例都有一個單獨的查詢。我不是特別喜歡這種方法,可能會添加新的模型類,但它現在可行。

到這裏看看: https://github.com/atk4/atk4-addons/blob/master/mvc/Model/MVCTable.php#L933

insertRecord()函數調用DSQL( '修改',假)幾次,構建查詢。最簡單的事情可能是:

function insertRecord($data=array()){ 
    $this->dsql('modify',false)->option('IGNORE'); 
    return parent::insertRecord($data); 
} 

插入記錄後,Agile Toolkit會自動嘗試加載新添加的記錄。但是,它會使用相關條件。我認爲,如果記錄被忽略,你會得到exception raised anyway。如有可能,請避免工作流程出現異常。例外情況是CPU密集型的,因爲它們捕獲回溯。

唯一的辦法可能是你完全重新定義insertRecord。這並不理想,但它可以讓你做你想要的單個查詢。

我更喜歡用loadBy(或getBy)手動檢查條件,因爲它考慮了模型條件和連接。例如,你可能在你的表上進行軟刪除,而MySQL密鑰不允許你進入,Model對於業務邏輯來說更有意義。

+0

這是一個很好的「窺探之下」,但它似乎有點過分複雜我的代碼...也許異常可以減少CPU密集的收集backtrace數據只需要,而不是在構造函數? (https://github.com/atk4/atk4/blob/master/lib/BaseException.php#L37) –

+0

只需要在這裏定義空collectBasicData https://github.com/atk4/atk4/blob/master/lib /Exception/InitError.php和類似的異常。 – romaninsh

相關問題