Laravel 保存多部分表单

Posted

技术标签:

【中文标题】Laravel 保存多部分表单【英文标题】:Laravel save multi part form 【发布时间】:2019-02-18 13:01:08 【问题描述】:

我有一个由 3 部分组成的表单,我希望能够在每次提交后更新数据库。有一个表格包含以下所有字段。

form1 asks for first and last name
form2 asks for email and phone
form3 asks for city and state

在我的控制器中,我有 3 个单独的函数来保存表单的每个步骤:

public function name(Request $request)
    $lead = Lead::firstOrNew(123);
    $lead->firstName = $request->get('firstName ');
    $lead->lastName = $request->get('lastName');
    $lead->save();
    return redirect('/form2');


public function info(Request $request)
    $lead = Lead::find(123);
    $lead->email = $request->get('email');
    $lead->phone = $request->get('phone');
    $lead->save();
    return redirect('/form3');


public function address(Request $request)
    $lead = Lead::find(123);
    $lead->city = $request->get('city');
    $lead->state = $request->get('state');
    $lead->save();
    return redirect('/done');

有没有办法将它与一个更新功能结合起来?

【问题讨论】:

【参考方案1】:

你可以重构方法来调用一个通用的“更新”函数。请参阅下面的示例代码。

public function name(Request $request)
    $this->update(123, $request);
    return redirect('/form2');


public function info(Request $request)
    $this->update(123, $request);
    return redirect('/form3');


public function address(Request $request)
    $this->update(123, $request);
    return redirect('/done');


private function update($id, $request) 
    $lead = Lead::find($id);
    foreach ($field as ['firstName', 'lastName', ...]) 
        if ($request->has($field)) 
            $lead->$field = $request->get($field);
        
    
    $lead->save();

【讨论】:

您必须将$request 作为参数传递给update 函数,否则它将不可用 好收获。更新【参考方案2】:

只需进行条件检查,更新模型并定义重定向 url:

public function info(Request $request) 
    $lead = Lead::firstOrNew(123);

    if ($request->has('firstName') && $request->has('lastName')) 
        $lead->firstName = $request->get('firstName ');
        $lead->lastName = $request->get('lastName');
        $redirect = '/form2';
     else if ($request->has('email') && $request->has('phone')) 
        $lead->email = $request->get('email');
        $lead->phone = $request->get('lastName');
        $redirect = '/form3';
     else if ($request->has('city') && $request->has('state')) 
        $lead->city = $request->get('city');
        $lead->state = $request->get('state');
        $redirect = '/done';
    

    $lead->save();

    return redirect($redirect);

另外,您可以通过update 进行组更新,只需确保将模型中的属性列入白名单

public function info(Request $request) 
    $lead = Lead::firstOrNew(123);
    $lead->update($request->all());

    if ($request->has('firstName') && $request->has('lastName')) 
        $redirect = '/form2';
     else if ($request->has('email') && $request->has('phone')) 
        $redirect = '/form3';
     else if ($request->has('city') && $request->has('state')) 
        $redirect = '/done';
    

    return redirect($redirect);

或者我最好在表单中添加一个重定向变量,例如:

<input type="hidden" name="redirect" value="form1">

并简化您的控制器方法,例如:

public function info(Request $request) 
    $lead = Lead::firstOrNew(123);
    $lead->update($request->all());

    return redirect($request->input('redirect'));

【讨论】:

【参考方案3】:

您可以为所有三个表单添加一个隐藏字段(但使用名称名称,例如form_name),并设置它们的值以识别表单(form1form2form3),当它是提交。然后在您的控制器中,检查请求中form_name 字段的值以确定您要重定向到的位置,如下所示:

public function info(Request $request) 
    $lead = Lead::firstOrNew(123);
    $lead->update($request->all());

    //this will be from the hidden field (form_name)
    $form_type = $request->get('form_name');

    if ($form_type == 'form1') 
        $redirect = '/form2';
     else if ($form_type == 'form2') 
        $redirect = '/form3';
     else if ($form_type == 'form3') 
        $redirect = '/done';
    

    return redirect($redirect);

【讨论】:

【参考方案4】:

如果您有使用 javascript 的选项,则将第一个和第二个表单数据保存在 cookie 或本地存储中,当用户到达表单的最后一部分时,然后从 cookie 或本地存储中取出数据,然后添加最后一个表单,但将它们保留在隐藏的输入中。

【讨论】:

【参考方案5】:

鉴于 HTTP 请求是无状态的(这意味着每个请求对它之前和之后的请求一无所知),我宁愿您使用会话,这样您就可以像 redirect 一样从一个 @ 存储信息987654322@ 给另一个。在这种情况下,您的代码应如下所示:

<?php

public function name(Request $request)
    Session::put('nameData', $request->all());   //Store the info from form1 in session and redirect to form2
    return redirect('/form2');


public function info(Request $request)
    $validSessionData = Session::has('nameData');

    if (!$validSessionData)     //Check if the user filled form1, if not, go back to form1
        return redirect('/form1');
    

    $nameAndInfo = Session::pull('nameData', []) + $request->all();  //Merge the info from form1 with info from form2. You could decide to keep them separate and merge later.

    Session::put('nameAndInfo', $nameAndInfo);
    return redirect('/form3');


public function address(Request $request)
    $validSessionData = Session::has('nameAndInfo');

    if (!$validSessionData)    Another check. You could also extend this by checking for form2 session data
        return redirect('/form1');
    

    $allData = Session::pull('nameAndInfo', []) + $request->all();  //Merge all session data
    $lead = Lead::firstOrNew(123);
    $lead->firstName = $allData['firstName'];
    $lead->lastName = $allData['lastName'];
    $lead->email = $allData['email'];
    $lead->phone = $allData['phone'];
    $lead->city = $allData['city'];
    $lead->state = $allData['state'];

    $lead->save();
    return redirect('/done');

【讨论】:

以上是关于Laravel 保存多部分表单的主要内容,如果未能解决你的问题,请参考以下文章

使用 Laravel 和 ajax 保存多维数组

Laravel Eloquent - 保存/更新相关的一对多关系数据

如何使用 laravel 将表单字段保存在 2 个表中

如果关系项不在 Laravel 的请求中,则删除它

Laravel 5.2 多模型 save()

Laravel - 注册不要在数据库中保存表单响应