1

我引用了http://agiletoolkit.org/codepad/newsletter上的 2 步时事通讯示例。我将示例修改为 4 步过程。以下页面类是第 1 步,它用于插入新记录并获取新记录 ID。问题是我不想在最后一步之前将此记录插入数据库。我不确定如何在不使用 save() 函数的情况下检索此 ID。任何想法都会有所帮助。

class page_Ssp_Step1 extends Page {
    function init(){
        parent::init();

        $p=$this;

        $m=$p->add(Model_Publishers);
        $form=$p->add('Form');
        $form->setModel($m);
        $form->addSubmit();
        if($form->isSubmitted()){

        $m->save();//inserts new record into db.
        $new_id=$m->get('id');//gets id of new record
        $this->api->memorize('new_id',$new_id);//carries id across pages
        $this->js()->atk4_load($this->api->url('./Step2'))->execute();
        }
    }
}
4

1 回答 1

1

有几种方法可以做到这一点,或者使用 atk4 功能、mysql 事务或作为应用程序设计的一部分。


1)自己管理id列

我假设您在 MySQL 中使用自动增量列,因此一个选项是不进行此自动增量,而是使用序列并选择下一个值并将其保存在您的 memorize 语句中,并使用 -> 将其作为 defaultValue 添加到模型中defaultValue($this->api->recall('new_id')


2)关闭自动提交并围绕插入创建事务

我来自 oracle 背景而不是 MySQL,但 MySQL 还允许您将多个语句包装在一个事务中,这可以保存所有内容或回滚,因此如果您可以创建事务,这也是一个选项,那么您仍然可以保存但如果所有步骤都完成,则只会提交填充多个表的完整事务。

在 atk 4.1 中,DBlite/mysql.php 类包含一些用于事务支持的函数,但agiletoolkit.org上的文档不完整,并且不清楚如何更改正在使用的 dbConnect,因为当前您使用连接到 lib/Frontend.php 中的数据库$this->dbConnect() 但没有传递参数的选项。

看起来您可以在第一页的开头使用它来执行所需的事务命令

 $this->api->db->query('SET AUTOCOMMIT=0');
 $this->api->db->query('START TRANSACTION');

然后根据需要在各个页面中插入。请注意,所做的一切都将包含在事务中,因此如果用户没有完成该过程,则不会保存任何内容。
在最后插入时,

 $this->api->db->query('COMMIT');

然后,如果您愿意,请重新打开自动提交,以便提交每个 SQL 语句

 $this->api->db->query('SET AUTOCOMMIT=1');

我还没有尝试过,但希望这会有所帮助。


3) 使用 beforeInsert 或 afterInsert

您还可以查看覆盖模型上的 beforeInsert 函数,该函数具有数据数组,但我认为如果您的 id 是一个自动增量列,它不会有值,直到 afterInsert 函数具有插入的 Id 的参数.


4) 使用状态来表示完整的记录

最后,您可以在记录中使用状态列来指示它仅处于第一阶段,并且只有在最后阶段完成时才会更新为完整状态。然后,您可以有一个定期运行的内务作业,以删除未完成所有阶段的记录。您在其中显示这些记录的任何网格或 crud 都将在模型中使用 AddCondition('status','C') 进行限制,或者在页面中添加,以便永远不会显示不完整的记录。

5)将事务管理为非sql

正如 Romans 所建议的,您可以将表单处理的结果存储在会话变量中,而不是直接存储到数据库中,然后在最后一步完成后使用 SQL 将其插入。

于 2012-07-28T20:35:40.373 回答