发送序列化的表单数据并接收带有表单和会话数据的 PHP Laravel 重定向

Posted

技术标签:

【中文标题】发送序列化的表单数据并接收带有表单和会话数据的 PHP Laravel 重定向【英文标题】:Send serialized form data and receive PHP Laravel redirect with form and session data 【发布时间】:2021-06-25 17:44:24 【问题描述】:

我的页面上有一个表格。提交后,我将在表单中添加其他数据以供提交。我可以通过 ajax 提交序列化的表单数据,但是,我无法成功处理响应。响应来自 Laravel,包括重定向 URL、会话“成功”或“错误”消息,以及表单错误重定向上可能的表单数据。

JS提交函数

function submit() 
    var formData = $('#form').serializeArray();
    formData.push( name: "additional_data", value: additional_data );
    $.ajax(
        type: "POST",
        url: "/submit_form_data",
        data: formData,
        success: function(data) 
            // response includes redirect url, session data ('success' or 'error' + message), form data (if form error)
        
    );

Laravel 数据提交路径

public function submitData(Request $request) 
    $data = $request->all();

    // check for form error and redirect back with error message and form input
    $validator = Validator::make($data);
    if ($validator->fails()) 
        return redirect()
            ->back()
            ->withErrors($validator)
            ->withInput();
    

    // submit data and redirect with success message
    $this->createEntry($data);
    return redirect('/dashboard')
      ->with('success', "Data successfully submitted");

我尝试通过 XMLHttpRequest 提交数据,但表单数据和会话数据似乎没有包含在请求响应中的任何位置。

function submit() 
    var formData = $('#form').serializeArray();
    formData.push( name: "additional_data", value: additional_data );
    var request = new XMLHttpRequest();
    request.onreadystatechange = function() 
        if (request.readyState == XMLHttpRequest.DONE) 
            // window redirects, but form data and session data are lost
            window.location.replace(request.responseURL);
        
    
    request.open("POST", '/submit_form_data');
    request.send(formData);

如果我通过简单的 $("#form").submit() 提交表单,则表单数据和会话数据都将原封不动地传输,但是,使用时似乎没有任何方法可以附加表单数据这种方法,所以我的“additional_data”丢失了。

最后一点。如果我在不等待 XMLHttpRequest.DONE 的情况下重定向,则会保留表单和会话数据。但是,在这种情况下,我不知道应该重定向到哪个 URL。

function submit() 
    var formData = $('#form').serializeArray();
    formData.push( name: "additional_data", value: additional_data );
    var request = new XMLHttpRequest();
    request.open("POST", '/submit_form_data');
    request.send(formData);
    // session data will be intact, but I don't have a redirect URL
    window.location.replace('/dashboard');

更新:

使用 hppycoder 的建议,我找到了一个可行的解决方案。

问题是前端所需的值需要通过 php 设置。这包括通过redirect()->withErrors($validator) 设置的$errors 变量,以及通过redirect()->withInput() 设置的表单输入数据。

但是,我需要能够在我的 javascript 中读取 php 响应。如果我返回一个 response()->json() 对象,我可以这样做,但是不会设置 $errors 和表单输入数据。

解决方法是结合这两种方法,虽然感觉不太优雅,因为它需要我多次调用我的 POST 方法。

Laravel 提交路径

public function submitData(Request $request) 
    $data = $request->all();

    // check for form error and redirect back with error message and form input
    $validator = Validator::make($data);
    if ($validator->fails()) 
        // this will set the necessary php values ($errors variable and form input data)
        // response cannot be read by ajax
        return redirect()
            ->back()
            ->withErrors($validator)
            ->withInput();
    

    // no form errors, submit data and return 'success' response
    $this->createEntry($data);
    // this response can be read by ajax, and the Session 'success' value is set
    Session::put('success', ("Data successfully submitted"));
    return response()->json([
        'success' => true
    ]);

JavaScript 提交函数

function submit() 
    var formData = $('#form').serializeArray();
    formData.push( name: "additional_data", value: additional_data );
    $.ajax(
        type: "POST",
        url: "/submit_form_data",
        data: formData,
        success: function(data) 
            if (data.success) 
                // check for 'success' and redirect to dashboard
                window.location.replace("/dashboard");
             else 
                // if no success message, reload current page with form errors and data
                // if I call window.location.reload() here, the form data and $errors variable are not set
                // in order to set these I need to submit the data a second time via XMLHttpRequest
                var form = document.getElementById('form');
                var formData = new FormData(form);
                formData.push( name: "additional_data", value: additional_data );
                var request = new XMLHttpRequest();
                request.open("POST", '/submit_form_data');
                request.send(formData);
                // now after reload, the form data and $errors varaible will be set
                window.location.reload();
            
        
    );

此外,下面是我的 html,它显示了刀片模板如何呈现 php 值。我应该在原始帖子中包含此内容,以阐明为什么需要设置 php 值。

<body>

    @if (count($errors->all()) > 0)
        <div class="alert alert-danger alert-block">
            <button type="button" class="close" data-dismiss="alert">&times;</button>
            <h4>Error</h4>
            Please check the form below for errors
        </div>
    @endif

    @if ($message = Session::get('success'))
        <div class="alert alert-success alert-block">
            <button type="button" class="close" data-dismiss="alert">&times;</button>
            <h4>Success</h4>
             $message 
        </div>
    @endif

    <form id="form" class="form-horizontal" role="form" method="POST" enctype="multipart/form-data">

        <div class="row form-group">
            <label class="control-label">Some Data</label>
            <input class="form-control" name="some_data" value=" old('some_data') ">
        </div>

        <div class="row">
            @if ($errors->has('some_data'))
                <span class="help-block">
                    <strong> $errors->first('some_data') </strong>
                </span>
            @endif
        </div>

    </form>

</body>

【问题讨论】:

你告诉 Laravel 返回一个redirect('/dashboard'),它将浏览器重定向到仪表板。你想要做的是有另一个端点来代替返回 JSON。这就是为什么你有一个重定向 URL 和一个成功消息 @hppycoder 我认为这对我来说很有意义。但是,应该使用哪种提交方式,ajax还是XMLHttpRequest,还是没有关系? 请求可以使用 jQuery 或 XMLHttpRequest,Laravel 响应是最重要的。 HTTP Responses 文档应该可以帮助您解决问题 【参考方案1】:

我将使用我之前发布的文档来展示。

public function submitData(Request $request) 
    $data = $request->all();

    // check for form error and redirect back with error message and form input
    $validator = Validator::make($data);
    if ($validator->fails()) 
        return redirect()
            ->back()
            ->withErrors($validator)
            ->withInput();
    

    // submit data and redirect with success message
    $this->createEntry($data);
    return response()->json([
        'success' => true,
        'message' => 'Data successfully submitted',
    ]);

JS 提交:

function submit() 
    var formData = $('#form').serializeArray();
    formData.push( name: "additional_data", value: additional_data );
    $.ajax(
        type: "POST",
        url: "/submit_form_data",
        data: formData,
        success: function(data) 
            console.log(data);
            // response includes redirect url, session data ('success' or 'error' + message), form data (if form error)
        
    );

【讨论】:

这让我非常接近我需要的地方。我可以使用 Session::put('success', $msg) 设置 Session 变量。但是,redirect()->withErrors($validator)->withInput() 也会将 $errors 变量与表单输入数据一起传递回我的视图。知道如何使用 json 响应来解决这个问题吗? 如果您希望在 AJAX 中处理输出,则不应重定向。这就是我在这里想说的,错误可以在 JSON 输出中传递并在 Javascript 中显示。 为了澄清一下,成功消息和错误都是由视图呈现的,这就是我尝试设置它们的原因。 我听到你对重定向的看法。我只是指出,当我使用 response() 和 redirect() 时,我的观点缺少某些东西。 对不起,如果我没有把事情说清楚。我知道我可以得到 JSON 形式的错误,但由于我的刀片模板已经在渲染 PHP 变量,我希望有一种方法可以继续将它们作为 PHP 而不是 JS 传递。

以上是关于发送序列化的表单数据并接收带有表单和会话数据的 PHP Laravel 重定向的主要内容,如果未能解决你的问题,请参考以下文章

获取发送表单数据并从 php 接收它

使用 ajax 和 mvc 提交带有照片数据的表单

如何接收隐藏文本框的输入并提交表单?

我如何在 Razor 页面中序列化表单并发送 JSON 请求 Ajax [重复]

表单提交/节点后防止页面重新加载(没有可用的 ajax)

插入并放入nodeJs + express api时,带有Redux Saga的Axios不发送表单数据