如何在控制器中处理多步表单?(当用户单击“转到第 2 步”时,控制器中未处理该表单)

5 php jquery laravel

我有一个使用 bootstrap 和 jQuery 的多步骤表单。多步骤形式用于用户购买产品。有4个步骤:第1步为用户输入他的信息(姓名,电子邮件等),第2步用户选择付款方式,第3步用户介绍付款数据,第4步为用户提供发票。所以我试图将表单分为 4 个步骤,每个步骤在控制器中都有一个相应的方法。

问题是,当用户单击提交输入“转到第 2 步”时,jquery 代码显示了第 2 步的部分供用户选择付款方式,但第 1 步并未在 PaymentController 中处理,即,请求未到达 PaymentController。

你知道问题出在哪里吗?

我对这个问题的流程:

我创建了一个 PaymentController 来处理付款过程。

用户单击产品并转到产品详细信息页面。在产品详细信息页面中,用户选择数量。所以在一个带有这个动作<form method="post" action="{{route('products.storeProduct', ['id' => $product->id, 'slug' => $product->slug])}}“>”的表单中有一个选择菜单。

这个表格的路线是:

Route::post('/product/{id}/{slug?}/payment', [
    'uses' => 'PaymentController@storeProduct',
    'as'   =>'products.storeProduct'
]);
Run Code Online (Sandbox Code Playgroud)

storeProduct 方法存储产品,从 db 获取一些信息,然后将用户重定向到 products.payment 路由以显示支付页面页面:

class PaymentController extends Controller
{
    public function storeProduct(Request $request, $id, $slug = null){
        ...
        return redirect(route('products.payment',['id' => $id, 'slug' => $slug]));
    }

    public function presentPaymentPage(Request $request, $id, $slug=null){
      ...
        return view('products.payment',
            ['product' => $product, 'id' => $id, 'slug' => $slug]);
    }
}
Run Code Online (Sandbox Code Playgroud)

presentPaymentPage() 的路由:

Route::get('/product/{id}/{slug?}/payment', [
    'uses' => 'PaymentController@presentPaymentPage',
    'as'   =>'products.payment'
]);
Run Code Online (Sandbox Code Playgroud)

然后对于第 2 步,我在 PaymentController 中创建了以下两个方法,并在 web.php 中创建了两个路由:

PaymentController 中添加了两个方法(暂时没有内容):

public function storeUserInfo(Request $request, $id, $slug = null){
    dd($request->all()); // dont shows nothing
}
public function presentPaymentMethods(Request $request, $id, $slug=null){

}
Run Code Online (Sandbox Code Playgroud)

以及方法的路线:

Route::post('/product/{id}/{slug?}/payment/storeUserInfo', [
    'uses' => 'PaymentController@storeUserInfo',
    'as'   =>'products.storeUserInfo'
]);

Route::get('/product/{id}/{slug?}/payment/paymentMethods', [
    'uses' => 'PaymentController@presentPaymentMethods',
    'as'   => 'products.presentPaymentMethods'
]);
Run Code Online (Sandbox Code Playgroud)

在payment.blade.php中,我有如下形式的步骤:

<div class="tab-content id="myTabContent">
    <div class="tab-pane fade show active clearfix" id="step1" role="tabpanel" aria-labelledby="home-tab">
        <form method="post" action="{{route('products.storeUserInfo', ['id' => $id, 'slug' => $slug])}}">
            <!-- form fields -->
            <input type="submit" href="#step2" data-toggle="tab" role="tab" class="next-step" value="Go to step 2"/>
        </form>
    </div>
    <div class="tab-pane fade clearfix" id="step2" role="tabpanel" aria-labelledby="profile-tab">
        <form method="post" class="clearfix">
            <!-- form fields -->
            <input type="submit" href="#step3" data-toggle="tab" role="tab" class="next-step" value="Go To step 3"/>
        </form>
    </div>
    ...
</div>
Run Code Online (Sandbox Code Playgroud)

csb*_*csb 3

所以看来多部分表单仅在客户端处理,并且不会返回到服务器。我相信这是 Bootstrap 中选项卡的预期行为。

根据您设置代码的方式,您有两个选择。

选项 1:在客户端处理多部分表单

您可以将页面上所需的所有信息存储在 JS 对象中或隐藏表单字段(甚至常规表单字段)中。在最后一步,<input type="submit" ... />按钮将提交到后端PaymentController

优点:不必在后端管理多部分状态。

缺点:您需要某种方法来检查产品是否仍然可用。例如,如果我在一两个小时后单击提交按钮,产品仍然可用吗?此外,将支付信息存储在客户端的某个位置可能不是一个好的做法,因为客户可能使用公共电脑。

选项 2:在后端处理多部分表单

修改您的视图文件,这样您就不会尝试纯粹在客户端用 JS 处理多步骤功能。这似乎更符合您想要做的事情,因为您有多个PaymentController与每个步骤相对应的操作。

为此,只需删除 Bootstrap 属性,即roledata-toggle等,然后在视图中使用 good 'olif/else语句来切换要显示的页面部分。

优点:似乎工作量更少,因为您已经完成了执行此操作的所有设置(除了您的视图文件)

缺点:每次用户单击按钮进入下一步时都需要回发。

希望这可以帮助。