2011-10-06 94 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

相关问题