Forms Silverstripe-在一个控制器上提交两个表单

Forms Silverstripe-在一个控制器上提交两个表单,forms,controller,silverstripe,Forms,Controller,Silverstripe,我试图用一个提交按钮将两个表单提交到同一控制器上各自的数据库 使用onAfterWrite我需要提交第一个表单获取其ID并将其传递给第二个表单,然后它提交第二个表单,然后重定向到成功 这是可能的还是应该用另一种方式 public static function FormAction1($data, $form) { $form->sessionMessage('Update successful', 'success'); $submission = Form1::get()->

我试图用一个提交按钮将两个表单提交到同一控制器上各自的数据库

使用onAfterWrite我需要提交第一个表单获取其ID并将其传递给第二个表单,然后它提交第二个表单,然后重定向到成功

这是可能的还是应该用另一种方式

public static function FormAction1($data, $form) {

 $form->sessionMessage('Update successful', 'success');
 $submission = Form1::get()->byID($data["ID"]);  
 $form->saveInto($submission);
 $submission->write();
 return Controller::curr()->redirectBack();

public static function FormAction2($data, $form) {

 $form->sessionMessage('Update successful', 'success');
 $submission = Form2::get()->byID($data["ID"]);  
 $form->saveInto($submission);
 $submission->write();
 return Controller::curr()->redirectBack();

一般来说,我建议以不同的方式构建代码以实现这一点

如果您有三个表单动作,其中一个执行另外两个动作,那么您可以将其构造为三个表单动作,根据它们的需求调用不同的方法。例如,假设您需要三个操作-“保存”、“通知用户”和“保存并通知用户”。我想这样安排:

class Page_Controller extends ContentController {
    public function Form() {
        $actions = new ArrayList([
            new FormAction('save', 'Save'),
            new FormAction('notify', 'Notify users'),
            new FormAction('saveandnotify', 'Save & Notify users')
        ]);

        return new Form($this, 'Form', $fields, $actions);
    }

    public function save($data, Form $form) {
        if($this->doSave($data, $form)) {
            $form->sessionMessage('Save successful', 'good');
        } else {
            $form->sessionMessage('Failed to save', 'bad');
        }

        return $this->redirectBack();
    }

    public function notify($data, Form $form) {
        if($this->doNotify($data, $form)) {
            $form->sessionMessage('Notified users successfully', 'good');
        } else {
            $form->sessionMessage('Failed to notify users', 'bad');
        }

        return $this->redirectBack();
    }

    public function saveandnotify($data, Form $form) {
        // First, attempt save
        if($this->doSave($data, $form)) {
            // Successful, so now notify users
            if($this->doNotify($data, $form)) {
                $form->sessionMessage('Saved and notified users', 'good');
            } else {
                $form->sessionMessage('Saved, but unable to notify users', 'bad');
            }
        } else {
            $form->sessionMessage('Unable to save or notify users', 'bad');
        }

        return $this->redirectBack();
    }

    /**
     * Saves data from a form submission.
     * @return bool true if save was successful, false if it failed
     */
    public function doSave($data, Form $form) {
        // ... your code here ...
    }

    /**
     * Notify users based on a form submission.
     * @return bool true if notification was successful, false if it failed
     */
    public function doNotify($data, Form $form) {
        // ... your code here ...
    }
}
这分离了表单操作处理和实际业务逻辑之间的关系,这还允许您更轻松地测试业务逻辑,而无需执行完整的表单提交(只需创建
表单
对象,设置值,然后运行测试)

一旦业务逻辑不可避免地变得过于复杂,单页控制器无法处理时,它还允许您将其移动到单独的类中。此时,我通常将提供各种业务功能的“服务”对象视为单独的解耦类

编辑:我也看到你现在在两个不同的班级里有这些表格。我假设这是两个独立的
表单
类还是两种不同的页面类型?在这种情况下,拥有一个服务类会有所帮助——这意味着您可以在所有页面类型中引用相同的逻辑(
doSave
doNotify


一般来说,我建议您以不同的方式构建代码以实现这一点

如果您有三个表单动作,其中一个执行另外两个动作,那么您可以将其构造为三个表单动作,根据它们的需求调用不同的方法。例如,假设您需要三个操作-“保存”、“通知用户”和“保存并通知用户”。我想这样安排:

class Page_Controller extends ContentController {
    public function Form() {
        $actions = new ArrayList([
            new FormAction('save', 'Save'),
            new FormAction('notify', 'Notify users'),
            new FormAction('saveandnotify', 'Save & Notify users')
        ]);

        return new Form($this, 'Form', $fields, $actions);
    }

    public function save($data, Form $form) {
        if($this->doSave($data, $form)) {
            $form->sessionMessage('Save successful', 'good');
        } else {
            $form->sessionMessage('Failed to save', 'bad');
        }

        return $this->redirectBack();
    }

    public function notify($data, Form $form) {
        if($this->doNotify($data, $form)) {
            $form->sessionMessage('Notified users successfully', 'good');
        } else {
            $form->sessionMessage('Failed to notify users', 'bad');
        }

        return $this->redirectBack();
    }

    public function saveandnotify($data, Form $form) {
        // First, attempt save
        if($this->doSave($data, $form)) {
            // Successful, so now notify users
            if($this->doNotify($data, $form)) {
                $form->sessionMessage('Saved and notified users', 'good');
            } else {
                $form->sessionMessage('Saved, but unable to notify users', 'bad');
            }
        } else {
            $form->sessionMessage('Unable to save or notify users', 'bad');
        }

        return $this->redirectBack();
    }

    /**
     * Saves data from a form submission.
     * @return bool true if save was successful, false if it failed
     */
    public function doSave($data, Form $form) {
        // ... your code here ...
    }

    /**
     * Notify users based on a form submission.
     * @return bool true if notification was successful, false if it failed
     */
    public function doNotify($data, Form $form) {
        // ... your code here ...
    }
}
这分离了表单操作处理和实际业务逻辑之间的关系,这还允许您更轻松地测试业务逻辑,而无需执行完整的表单提交(只需创建
表单
对象,设置值,然后运行测试)

一旦业务逻辑不可避免地变得过于复杂,单页控制器无法处理时,它还允许您将其移动到单独的类中。此时,我通常将提供各种业务功能的“服务”对象视为单独的解耦类

编辑:我也看到你现在在两个不同的班级里有这些表格。我假设这是两个独立的
表单
类还是两种不同的页面类型?在这种情况下,拥有一个服务类会有所帮助——这意味着您可以在所有页面类型中引用相同的逻辑(
doSave
doNotify


你有什么理由需要两张表格吗?你不能对一个表单做同样的操作吗?它们目前在两个单独的页面上,但我希望它们都在一个页面上,这样用户就可以多点击一次。它们是不同的实体,因此无法将它们放在同一个表中。将需要分开。但是您的操作处理程序都采用相同的数据作为输入,对吗?或者,如果用户没有机会填写内容,应该如何填充第二个表单数据?也许你应该澄清你的问题…你有什么理由需要两张表格吗?你不能对一个表单做同样的操作吗?它们目前在两个单独的页面上,但我希望它们都在一个页面上,这样用户就可以多点击一次。它们是不同的实体,因此无法将它们放在同一个表中。将需要分开。但是您的操作处理程序都采用相同的数据作为输入,对吗?或者,如果用户没有机会填写内容,应该如何填充第二个表单数据?也许你应该澄清你的问题…