我正在数据库中实现订阅。电子邮件必须是唯一的,因此我在数据库中有一个UNIQUE索引。我在我的页面init中有这个代码:
$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 :(得分:1)
这是一种方法:
https://github.com/atk4/atk4-web/blob/master/lib/Model/ATK/User.php#L95
虽然如果要对复制执行自定义操作,您应该将getBy移到模型之外,进入页面逻辑。
答案 1 :(得分:0)
正如@Col建议的那样,我们想要使用“insert ignore”。
$ 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('modify',false)来构建查询。你可以做的最简单的事情是:
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和模型方式对于业务逻辑也更有意义。
答案 2 :(得分:-1)
为什么不想运行简单的选择来检查电子邮件是否已被占用?
或者让它INSERT IGNORE然后检查affected_rows