我有以下代码:
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
当错误是由于重复键引起的时,如何自定义消息?
理想情况下,您会在尝试运行插入语句
之前验证模型,请查看唯一的验证程序。
将类似这样的规则添加到模型中
// 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());
尤其成问题,因为您可能会将敏感数据暴露给现实世界的用户,这是一个很大的安全问题。
这种方法对我不起作用:
[['a1', 'a2'], 'unique', 'targetAttribute' => ['a1', 'a2'], 'message' => 'custom message'],
我根据这个答案尝试了这个,它奏效了:
['a1', 'compare', 'compareAttribute' => 'a2', 'operator' => '!=', 'message' => 'your error message...'],
编辑:
但是,如果我正确理解了您的问题,这不是您想要的。您想捕获由于在同一表中插入两个相等的主键而导致的错误吗?为什么不使用自动增量主键?
无论如何,您可以使用这样的东西:
[['id'], 'exist', 'skipOnError' => true, 'targetClass' => YourModel::className(), 'targetAttribute' => ['id' => 'YourModelId']],