如何在Laravel中验证多条记录的插入?

3
我的应用程序有一个表单,我要插入多条记录,每条记录都是一个新的表单。我想验证每个表单中的每个字段,我尝试使用验证函数,但我不知道如何在多条记录插入时进行验证?对于这个项目,我正在使用laravel 5.2。
多个插入的存储函数
public function store(Request $request)
    {
        $this->validate($request,[
            'name' => 'required|min:4',
            'fname' => 'required',
            'rollno' => 'required|unique:students'
        ]);
        $input = $request->all();
        $condition = $input['name'];
        foreach ($condition as $key => $condition) {
            $student = new Student;
            $student->name = $input['name'][$key];
            $student->fname = $input['fname'][$key];
            $student->rollno = $input['rollno'][$key];
            $student->obtainedmarks = $input['obtainedmarks'][$key];
            $student->totalmarks = $input['totalmarks'][$key];
            $student->percentage = $input['percentage'][$key];
            $student->save();
        }
        return Redirect::to('/allresults');

}

插入数据的视图

@extends('layouts.app')
@section('content')
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

<script type="text/javascript">
    $(function () {
        $('.add').click(function () {
            var n = ($('.resultbody tr').length - 0) + 1;
            var tr = '<tr><td class="no">' + n + '</td>' +
                    '<td><input type="text" class="name form-control" name="name[]" value="{{ old('name') }}"></td>'+
                    '<td><input type="text" class="fname form-control" name="fname[]" value="{{ old('fname') }}"></td>'+
                    '<td><input type="text" class="rollno form-control" name="rollno[]" value="{{ old('rollno') }}"></td>'+
                    '<td><input type="text" class="obtainedmarks form-control" name="obtainedmarks[]" value="{{ old('email') }}"></td>'+
                    '<td><input type="text" class="totalmarks form-control" name="totalmarks[]"></td>'+
                    '<td><input type="text" class="percentage form-control" name="percentage[]"></td>'+
                    '<td><input type="button" class="btn btn-danger delete" value="x"></td></tr>';
            $('.resultbody').append(tr);
        });

        $('.resultbody').delegate('.delete', 'click', function () {
            $(this).parent().parent().remove();
        });

        $('.resultbody').delegate('.obtainedmarks , .totalmarks', 'keyup', function () {
            var tr = $(this).parent().parent();
            var obtainedmarks = tr.find('.obtainedmarks').val() - 0;
            var totalmarks = tr.find('.totalmarks').val() - 0;

            var percentage = (obtainedmarks / totalmarks) * 100;
            tr.find('.percentage').val(percentage);
        });
    });
</script>

<div class="container">
    <div class="row">
        <div class="col-md-10 col-md-offset-1">
            <div class="panel panel-default">
                <div class="panel-heading">Add Results</div>
                @if(count($errors) >0 )
                    <ul>
                        @foreach($errors->all() as $error)
                            <li>{{$error}}</li>
                        @endforeach
                    </ul>
                @endif
                <div class="panel-body">
                   <form class="form-horizontal" role="form" method="POST" action="{{ url('/result') }}">
                        {!! csrf_field() !!}
                    <table class="table table-striped">
                            <thead>
                                <tr>
                                    <th>ID</th>
                                    <th>Student Name</th>
                                    <th>Father Name</th>
                                    <th>Roll No</th>
                                    <th>Obtained Marks</th>
                                    <th>Total Marks</th>
                                    <th>%</th>
                                    <th>Delete</th>
                                </tr>
                            </thead>
                            <tbody class="resultbody">
                                <tr>
                                    <td class="no">1</td>
                                    <td>
                                        <input type="text" class="name form-control" name="name[]" value="{{ old('name') }}">
                                    </td>
                                    <td>
                                        <input type="text" class="fname form-control" name="fname[]" value="{{ old('fname') }}">
                                    </td>
                                    <td>
                                        <input type="text" class="rollno form-control" name="rollno[]" value="{{ old('rollno') }}">
                                    </td>
                                    <td>
                                        <input type="text" class="obtainedmarks form-control" name="obtainedmarks[]" value="{{ old('email') }}">
                                    </td>
                                    <td>
                                        <input type="text" class="totalmarks form-control" name="totalmarks[]">
                                    </td>
                                    <td>
                                        <input type="text" class="percentage form-control" name="percentage[]">
                                    </td>
                                    <td>
                                        <input type="button" class="btn btn-danger delete" value="x">
                                    </td>
                                </tr>

                            </tbody>
                        </table>    
                        <center><input type="button" class="btn btn-lg btn-primary add" value="Add New Item">   
                        <input type="submit" class="btn btn-lg btn-default" value="Submit"></center>
                        </form>
                </div>
            </div>
        </div>

    </div><!-- First Row End -->
</div> <!-- Container End -->

@endsection

更新:在视图中,您会注意到有一个按钮,当用户点击“添加新行”时,它会添加新的一行。我想验证所有行,每行都包含一条记录。 enter image description here


您可以使用通配符验证。 - Nahid Bin Azhar
你能详细说明一下吗,@NahidBinAzhar? - user6060368
请参阅文档 https://laravel.com/docs/5.2/validation#validating-arrays。 - Nahid Bin Azhar
5个回答

7
我认为您可以使用以下方法验证您的数组输入。
'input_name.*' => 'rules'

在您的情况下,这样做:

https://laravel.com/docs/5.2/validation#validating-arrays


这是关于验证数组的Laravel文档链接。
$this->validate($request,[
     'name.*'   => 'required|min:4',
     'fname.*'  => 'required',
     'rollno.*' => 'required|unique:students'
 ]);

它输出了helpers.php文件的523行错误异常: htmlentities()函数期望第一个参数为字符串,但实际传入的是数组(视图:D:\xampp\htdocs\ngresulty\resources\views\students\addresult.blade.php)。 - user6060368
这是因为你试图获取“旧输入”。但由于它是一个数组,你需要这样做:{{ old('name.index') }} - z3r0ck
是的,我也在视频中看到了这个,但它对我不起作用,我从代码中删除了所有旧的('input')。 - user6060368
可能是这个问题。你可以尝试在视图文件的开头使用 dd($errors); 命令来查看错误信息。 - z3r0ck
让我们在聊天中继续这个讨论。点击此处进入聊天室 - z3r0ck
显示剩余4条评论

4

Laravel 5.2提供了许多现成的功能,对于数组验证,您可以查看验证数组

在您的情况下,您应该尝试:

   $validator = \Validator::make($request->all(), [
            'name.*' => 'yourRules',
            'fname.*' => 'yourRules',
            'rollno.*' => 'yourRules',
            'obtainedmarks.*' => 'yourRules',
            'totalmarks.*' => 'yourRules'
        ]);

  if($validator->fails()) {
            return back()->withInput()->withErrors($validator->errors());
  }

另一种解决方案:

以上解决方案是完美的,也是最新的解决方案,特别适用于Laravel 5.2用户。你也可以尝试

$validator = \Validator::make($request->all(), [
    'name' => 'array',
    //and your other rules here
]);

然后使用Validator的each方法来将你定义的规则应用到数组中的每个元素。

$validator->each('name','yourRule');

我之前尝试过,但整个问题是那个 Validator 类中的 \ 符号。已解决! - user6060368

2
输入数组会使事情变得更加复杂。您正在各个层面上犯错误:
  • 没有考虑行索引位置。
  • Blade仅在可能存在多个行时渲染一行。
  • javascript中的Blade语法永远不会起作用。
  • 从未调用验证器。
  • 保存有效记录时,没有考虑到如果其中一个记录无效,则必须返回用户。
    • 选择仅返回无效行会增加一些工作,但可以完成。

尝试以下作为起点。我现在没有时间测试所有内容,但它遵循我成功使用过的逻辑。

视图

@extends('layouts.app')
@section('content')
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

<script type="text/javascript">
    $(function () {
        $('.add').click(function () {
            var n = $('.resultbody tr').length - 0;
            var n_adj = n + 1;
            var tr = '<tr><td class="no">' + n_adj + '</td>' +
                    '<td><input type="text" class="name form-control" name="name[n]" value=""></td>'+
                    '<td><input type="text" class="fname form-control" name="fname[n]" value=""></td>'+
                    '<td><input type="text" class="rollno form-control" name="rollno[n]" value=""></td>'+
                    '<td><input type="text" class="obtainedmarks form-control" name="obtainedmarks[n]" value=""></td>'+
                    '<td><input type="text" class="totalmarks form-control" name="totalmarks[n]"></td>'+
                    '<td><input type="text" class="percentage form-control" name="percentage[n]"></td>'+
                    '<td><input type="button" class="btn btn-danger delete" value="x"></td></tr>';
            $('.resultbody').append(tr);
        });

        $('.resultbody').delegate('.delete', 'click', function () {
            $(this).parent().parent().remove();
        });

        $('.resultbody').delegate('.obtainedmarks , .totalmarks', 'keyup', function () {
            var tr = $(this).parent().parent();
            var obtainedmarks = tr.find('.obtainedmarks').val() - 0;
            var totalmarks = tr.find('.totalmarks').val() - 0;

            var percentage = (obtainedmarks / totalmarks) * 100;
            tr.find('.percentage').val(percentage);
        });
    });
</script>

<div class="container">
    <div class="row">
        <div class="col-md-10 col-md-offset-1">
            <div class="panel panel-default">
                <div class="panel-heading">Add Results</div>
                @if(count($errors) >0 )
                    <ul>
                        @foreach($errors->all() as $error)
                            <li>{{$error}}</li>
                        @endforeach
                    </ul>
                @endif
                <div class="panel-body">
                   <form class="form-horizontal" role="form" method="POST" action="{{ url('/result') }}">
                        {!! csrf_field() !!}
                    <table class="table table-striped">
                            <thead>
                                <tr>
                                    <th>ID</th>
                                    <th>Student Name</th>
                                    <th>Father Name</th>
                                    <th>Roll No</th>
                                    <th>Obtained Marks</th>
                                    <th>Total Marks</th>
                                    <th>%</th>
                                    <th>Delete</th>
                                </tr>
                            </thead>
                            <tbody class="resultbody">

                                @for ($i = 0; $i < isset($row_count) ? $row_count : 1; $i++)
                                <tr>
                                    <td class="no">{{ $i+1 }}</td>
                                    <td>
                                        <input type="text" class="name form-control" name="name[]" value="{{ old('name['.$i.']', null) }}">
                                    </td>
                                    <td>
                                        <input type="text" class="fname form-control" name="fname[]" value="{{ old('fname['.$i.']', null) }}">
                                    </td>
                                    <td>
                                        <input type="text" class="rollno form-control" name="rollno[]" value="{{ old('rollno['.$i.']', null) }}">
                                    </td>
                                    <td>
                                        <input type="text" class="obtainedmarks form-control" name="obtainedmarks[]" value="{{ old('obtainedmarks['.$i.']', null) }}">
                                    </td>
                                    <td>
                                        <input type="text" class="totalmarks form-control" name="totalmarks[]" value="{{ old('totalmarks['.$i.']', null) }}">
                                    </td>
                                    <td>
                                        <input type="text" class="percentage form-control" name="percentage[]" value="{{ old('percentage['.$i.']', null) }}">
                                    </td>
                                    <td>
                                        <input type="button" class="btn btn-danger delete" value="x">
                                    </td>
                                </tr>
                                @endfor

                            </tbody>
                        </table>    
                        <center><input type="button" class="btn btn-lg btn-primary add" value="Add New Item">   
                        <input type="submit" class="btn btn-lg btn-default" value="Submit"></center>
                        </form>
                </div>
            </div>
        </div>

    </div><!-- First Row End -->
</div> <!-- Container End -->

@endsection

store()

use Validator;

// ...

public function store(Request $request)
    {

        $validation_rules = [
            'name' => 'required|min:4',
            'fname' => 'required',
            'rollno' => 'required|unique:students'
        ];

        $validation_messages = [
            // add custom error messages
        ];

        $name = $request->input('name');
        $fname = $request->input('fname');
        $rollno = $request->input('rollno');
        $obtainedmarks = $request->input('obtainedmarks');
        $totalmarks = $request->input('totalmarks');
        $percentage = $request->input('percentage');

        // number of rows submitted (use a required value)
        $n = count($names);

        // track valid student records
        $students = [];

        for ($i=0; $i < $n; $i++) {
            $data = [
                'name' => $name[$i],
                'fname' => $fname[$i],
                'rollno' => $rollno[$i],
                'obtainedmarks' => $obtainedmarks[$i],
                'totalmarks' => $totalmarks[$i],
                'percentage' => $percentage[$i]
            ];
            $validator = Validator::make($data, $validation_rules, $validation_messages);

            if ($validator->fails()) {
                // redirect back to form
                return redirect()->back()->withInput($request->all())->with('errors', '$validator->errors());
            }

            $students[] = $data;
        }

        foreach ($students as $row) {
            Student::create($row);
        }

        return redirect('/allresults');

}

不考虑行索引位置。我完全不同意那个说法。看看这个:http://adamwathan.me/2016/04/06/cleaning-up-form-input-with-transpose/ - Álvaro Guimarães
@ÁlvaroGuimarães,Transpose 看起来很有趣... 你不同意哪部分陈述?请看一下所提出的问题,并指出代码在哪里使用了 Transpose 或者为动态行数指定了所需的行索引。 - Qevo
我的评论看起来很粗鲁,这不是我的本意,抱歉。我不同意的陈述是:“不考虑行索引位置”。你的回答是正确的,但我不认为你需要控制行索引位置。 - Álvaro Guimarães
@ÁlvaroGuimarães,感谢您的考虑,但我向您保证,我没有将您的评论视为粗鲁。一旦我到达了我分享的代码,我就停止了测试,所以我不能说没有指定行索引位置它不起作用,只是似乎blade必须逐行创建,而我不确定old()如何知道当前循环中哪一行是相关的。 - Qevo

0
$failed = false;
$errors = [];
        foreach($data['name'] as $key => $val){

            $v = Validator::make($val, [
                        'name' => 'unique:users'
             ]);



             if ($validator->fails()) {
                $failed = true;
                 $error = [
                     'msg' => $v->errors()->all(),
                     'number' => $val['name'],
                 ];
                 array_push($errors, $error); 
             }

        }

if($failed == true){
    return['msg' => false, 'data' => $errors];
}

试试这个 :)


创建多个验证器实例并不是最好的解决方案,Laravel可以验证数组。 - Christian Giupponi

0
对于多条记录的验证,可以像这样使用自定义消息和记录编号。
<?php

namespace App\Http\Requests\Modules\Export\ExportBooking;

use App\Rules\PhoneRule;
use App\Traits\ApiResponser;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;


class ExportBookingCreateRequest extends FormRequest
{
    use ApiResponser;

    public function rules()
    {
        $rules = [
            'booking_date' => 'required|date',
            'exp_organization_id' => ['required','integer', Rule::exists('organization', 'id')->where('is_export', 1) ],
            'marketing_person_id' => 'required|integer|exists:marketing_person,id',
            'customer_id' => 'required|integer|exists:customer,id',

            'exp_booking_dtl' => 'required',
        ];

        $exp_booking_dtl = $this->input('exp_booking_dtl');

        foreach ($exp_booking_dtl as $rowNumber => $item) {
            $rules["exp_booking_dtl.{$rowNumber}.product_id"] = "required|integer|exists:product,id";
            $rules["exp_booking_dtl.{$rowNumber}.product_sticker_id"] = "required|integer|exists:product_sticker,id";
            $rules["exp_booking_dtl.{$rowNumber}.po_number_id"] = "nullable|integer|exists:po_number,id";
            $rules["exp_booking_dtl.{$rowNumber}.qty"] = "required|numeric|gt:0";
        }
        return $rules;
    }
    public function messages()
    {
        $messages = [];
        $exp_booking_dtl = $this->input('exp_booking_dtl');

        foreach ($exp_booking_dtl as $rowNumber => $item) {

            $messages["exp_booking_dtl.{$rowNumber}.product_id.required"] = "Booking Detail Rec-".($rowNumber+1).": Product is required.";
            $messages["exp_booking_dtl.{$rowNumber}.product_id.exists"] = "Booking Detail Rec-".($rowNumber+1).": Invalid Product.";

            $messages["exp_booking_dtl.{$rowNumber}.product_sticker_id.required"] = "Booking Detail Rec-".($rowNumber+1).": Product Sticker is required.";
            $messages["exp_booking_dtl.{$rowNumber}.product_sticker_id.exists"] = "Booking Detail Rec-".($rowNumber+1).": Invalid Product Sticker.";

            $messages["exp_booking_dtl.{$rowNumber}.po_number_id.exists"] = "Booking Detail Rec-".($rowNumber+1).": Invalid PO Number.";

            $messages["exp_booking_dtl.{$rowNumber}.qty.required"] = "Booking Detail Rec-".($rowNumber+1).": Qty is required.";
            $messages["exp_booking_dtl.{$rowNumber}.qty.gt"] = "Booking Detail Rec-".($rowNumber+1).": Qty must be greater than :value.";
        }
        return $messages;
    }
    public function failedValidation(Validator $validator)
    {
        throw new HttpResponseException(
            $this->set_response(null, 422, 'error', $validator->errors()->all(), new Request($this->request->all()))
        );
    }
}



网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接