Transactions Yii2当使用事务进行多步骤注册时,那么就退一步如何检索数据

Transactions Yii2当使用事务进行多步骤注册时,那么就退一步如何检索数据,transactions,yii2,Transactions,Yii2,当前实施情况 目前我正在使用多步骤注册,我总共有3个步骤 最后一步是确认输入的所有数据,然后提交 现在,我在步骤1的最开始使用transaction,如: $transaction = Yii::$app->db->beginTransaction(); 如果在我使用的任何点执行失败 $transaction->rollBack(); 从数据库回滚所有条目的步骤 现在,如果一切都执行得很好,并且在最后一步中,用户确认输入的数据并提交,我会将所有数据保存在db中,如: $tr

当前实施情况

目前我正在使用多步骤注册,我总共有3个步骤

最后一步是确认输入的所有数据,然后提交

现在,我在步骤1的最开始使用transaction,如:

$transaction = Yii::$app->db->beginTransaction();
如果在我使用的任何点执行失败

$transaction->rollBack();
从数据库回滚所有条目的步骤

现在,如果一切都执行得很好,并且在最后一步中,用户确认输入的数据并提交,我会将所有数据保存在db中,如:

$transaction->commit();
问题

现在,由于我正在使用多步骤注册,如果任何时候用户想要返回到上一步,那么如何检索填充的数据

我们无法从表中检索数据,因为直到最后一个commit语句,我们还并没有将任何内容存储到数据库中

当前解决方案


一种解决方案是使用会话存储临时数据,但我正在寻找任何其他方法

如果您对每个步骤使用新操作(以及一个名为“注册”的表,即),那么对于每个操作,您可以传递注册
id
,并根据步骤编号加载字段。 因此,让我们考虑你有一个登记表,包括“代码>名称<代码> >代码>姓氏<代码> >代码>年龄<代码> >代码>性别>代码>字段,在步骤1中填写<代码>名称<代码> >代码>姓氏< /代码>,在步骤2填写<代码>年龄< /代码>和<代码>性别<代码>。您的模型将如下所示:

class Registration extends \yii\db\ActiveRecord
{
    const SCENARIO_STEP1 = 'step1';
    const SCENARIO_STEP2 = 'step2';

    public function scenarios()
    {
        return [
            self::SCENARIO_STEP1 => ['name', 'surname'],
            self::SCENARIO_STEP2 => ['age', 'gender'],
        ];
    }

    public function rules()
    {
        ... your validation for fields...

请注意,此处的场景非常重要,可以在精确步骤中对某些精确字段进行验证(有关您可以从中阅读的场景的更多信息)

第一步的行动如下:

public function actionStep1()
{
    $model = new Registration();
    $model->setScenario(Registration::SCENARIO_STEP1);

    if ($model->load(Yii::$app->request->post()) && $model->save()) {
        return $this->redirect(['step-2', 'id' => $model->id]);
    } else {
        return $this->render('step-1', [
            'model' => $model,
        ]);
    }
}
step-1
视图中,您有需要填写的
name
姓氏
字段,其中验证只适用于
场景()
方法中列出的字段。然后在第二步操作中,代码如下所示:

public function actionStep2($id)
{
    $model = Order::findOne($id);
    $model->setScenario(Order::SCENARIO_STEP2);

    if ($model->load(Yii::$app->request->post()) && $model->save()) {
        return $this->redirect(['finish', 'id' => $model->id]);
    } else {
        return $this->render('step-2', [
            'model' => $model,
        ]);
    }
}
。。如您所见,在第二步中,我们传递已经存在的注册模型的
id
,并继续填充其属性。根据您有多少步骤,您可以从第二步重定向到第三步,或者显示finish消息并执行一些您需要的其他逻辑

我认为您对如何使用事务的想法有点错误,因为事务是保存数据库中的行的方式(防止在进行更改时在其他地方更改这些行)

进行多步骤注册的另一种方法是在单个页面中包含所有步骤,并根据您的阶段显示/隐藏所需字段(例如使用JQuery)。我记得已经回答过这类问题,但找不到链接。。如果我成功了,我一定会更新我的答案


希望我的回答是有帮助的

为了尽可能多地保留解决方案而不是用户会话存储,那么我会说使用ajax请求对每个步骤进行验证

更详细地说

  • 用户输入url,如用户/注册#步骤1
  • 填表
  • 单击下一步
  • 发送AJAX请求以验证发送的数据
  • 如果验证成功,则转至步骤2,如“用户/注册#步骤2”
  • 步骤1表单隐藏,步骤2表单使用javascript显示
  • 如果验证失败,则显示消息并保持当前步骤
这样,您就可以返回到上一步并填写表单,因为没有重新加载页面。(步骤使用url哈希)

在每个步骤中,除最后一步外,您可以使用:

$transaction = Yii::$app->db->beginTransaction();
保存您的模型

最后,回滚所有更改。(成功和失败)

通过这种方式,您可以确保数据可以保存在数据库中(可能您的数据库有规则中未定义的限制),而无需实际保存任何内容

在最后一步中,您将收集所有步骤中的所有数据:

$transaction = Yii::$app->db->beginTransaction();
保存模型,并在验证后提交更改

$transaction->commit();

据我所知,如果您使用了事务,那么在您使用$transaction->commit()提交之前,它不会在db中创建任何记录;现在使用事务的原因是希望避免数据库中任何未完成的数据,比如有人在两者之间留下了注册。是的,但事务通常使用很短的时间。例如,你有一个银行账户。考虑一下你支付了一些服务,同时有人把一些钱转给你(在你提交你的交易之前,他不能这么做)。我的意思是交易是在一个脚本中进行的,所以您不能将其传递给另一个操作。。。(它将简单地回滚)
$transaction->commit();