2

我正在数据库中实现订阅。电子邮件必须是唯一的,所以我在数据库中有一个唯一的索引。我的页面初始化中有这段代码:

$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 消息,这是检测错误是否来自重复条目的唯一方法吗?

4

3 回答 3

1

这是一种方法:

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

虽然如果您想对复制执行自定义操作,您应该将 getBy 移到模型之外,进入页面的逻辑。

于 2011-10-07T00:41:01.087 回答
0

正如@Col 建议的那样,我们想使用“插入忽略”。

$form->update() 依赖于 Model->update() 然后依赖 DSQL 类来构建查询。DSQL 确实支持 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 会自动尝试加载新添加的记录。但是,它将使用相关条件。我认为,如果忽略记录,无论如何都会引发异常。如果可能,请避免工作流程中出现异常。异常是 CPU 密集型的,因为它们捕获回溯。

唯一的方法可能是您完全重新定义 insertRecord。这并不理想,但它可以让您按照自己的意愿进行单个查询。

我更喜欢使用 loadBy(或 getBy)手动检查条件,因为它考虑了模型条件和连接。例如,您的表可能有软删除,虽然 MySQL 键不允许您输入,但 Model 会,并且模型方式对于业务逻辑也更有意义。

于 2011-10-07T01:00:14.850 回答
-1

为什么不想运行简单的选择来检查电子邮件是否已被占用?

或者让它 INSERT IGNORE 然后检查affected_rows

于 2011-10-06T11:11:12.053 回答