2017-08-10 125 views
0

我有以下代碼:Yii2:自定義錯誤消息時完整性約束違規

try { 
    if ($model->save()) { 
     return $this->redirect(['view', 'id' => $model->id]); 
    } 
} catch (\Exception $e) { 
    $model->addError(null, $e->getMessage()); 
    return $this->render('create', [ 
     'model' => $model, 
    ]); 
} 

但是當我做一個插入與重複鍵的數據庫,顯示的錯誤是不是很友好。

SQLSTATE [23000]:完整性約束違規:1062重複條目 '1-17' 的執行關鍵 '主要' 的SQL是:INSERT_QUERY

如何自定義的消息時,錯誤是由於重複鍵?

回答

1

在嘗試運行插入語句之前,您會理想地驗證模型
看看unique validator

這樣一個規則添加到模型

// a1 and a2 need to be unique together, and they both will receive error message 
[['a1', 'a2'], 'unique', 'targetAttribute' => ['a1', 'a2'], 'message' => 'custom message'], 

調用model->save()應該只是返回false,加入適當的錯誤消息,並且不會引發任何異常


編輯:
什麼我試圖在評論中說,做這樣的事情一般不是一個好主意:

try { 
    if ($model->save()) { 
     return $this->redirect(['view', 'id' => $model->id]); 
    } 
} catch (\Exception $e) { 
    $model->addError(null, $e->getMessage()); 
    return $this->render('create', ['model' => $model]); 
} 

這應該只是成爲

if ($model->save()) { 
    return $this->redirect(['view', 'id' => $model->id]); 
} 
return $this->render('create', ['model' => $model]); 

如果發生任何異常,prod環境下真實的用戶只會看到一個通用的狀態500消息。這就是爲什麼我們事先進行驗證,以防止例外情況不會在地毯下清掃它們。

這樣$model->addError(null, $e->getMessage());是你的風險敏感數據暴露在真實世界中的用戶這是一個很大的安全隱患問題尤其嚴重。

+0

我想補充一點'完整性約束violation's可以在其他情況下發生的,以及(大部分是無效的插入/更新/刪除外鍵字段)。這個例子只是防止一個場景(重複PK)。正確的方法是確定這些發生的位置,並防止應用程序試圖通過對用戶有意義的驗證規則和錯誤消息來運行它們,而不是定製異常消息 – csminb

+0

您能否解釋您的評論?你可以編輯你的答案:)謝謝! – Giest

+2

@Giest我想說你的重點應該是防止[違反約束](https://dev.mysql.com/doc/ndbapi/en/ndb-error-codes-constraint-violation.html)使用更嚴格的驗證規則。我希望編輯的答案可以幫助你。歡呼 – csminb

1

這種方法並沒有爲我工作:

[['a1', 'a2'], 'unique', 'targetAttribute' => ['a1', 'a2'], 'message' => 'custom message'], 

我想這個基礎上,this answer和它的工作:

['a1', 'compare', 'compareAttribute' => 'a2', 'operator' => '!=', 'message' => 'your error message...'], 

編輯:

但是,如果我理解你的問題正確地說,這不是你想要的。你想捕獲由於在同一個表中插入兩個相等的主鍵而導致的錯誤?爲什麼不使用自動增量主鍵?

反正你可以使用這樣的事情:

[['id'], 'exist', 'skipOnError' => true, 'targetClass' => YourModel::className(), 'targetAttribute' => ['id' => 'YourModelId']], 
+0

引用來自你所鏈接的答案:'因爲唯一的驗證器驗證屬性值在表中是唯一的「,所鏈接的問題和OP的問題完全不同 – csminb

+0

是的,我不確定我是否正確理解他的問題,這就是爲什麼我編輯了我的答案,但我還不確定。我希望我不會混淆比我更幫忙.. – ManuelCash

+1

是的,我的桌子有兩個主鍵。我不想使用自動增量,因爲我不想要多於一組鍵。我只想要一條消息來替換錯誤「SQLSTATE [23000]:完整性約束違規:1062重複...」 – Giest

相關問題