【问题标题】:Laravel array validation: use field index in error messageLaravel 数组验证:在错误消息中使用字段索引
【发布时间】:2019-12-22 03:25:35
【问题描述】:

我正在尝试验证一个字段数组,我想指出验证错误中哪个字段有误。

我有一个表格可以上传多张图片。对于每个图像,HTML 必须有一个 captionalt 属性。如果我尝试上传 3 张图片并错过了其中两张的字段,我会收到如下错误消息:

The field 'image file' is required.
The field 'image caption' is required.
The field 'image alt' is required.
The field 'image caption' is required.
The field 'image alt' is required.
The field 'image file' is required.

问题是:attribute 重复了,如果用户想要更新多张图片,他/她必须检查所有图片以查找缺少哪个字段!

我想要的是这个:

The field 'image file (item 1)' is required.
The field 'image caption (item 1)' is required.
The field 'image alt (item 1)' is required.
The field 'image caption (item 3)' is required.
The field 'image alt (item 3)' is required.
The field 'image file (item 1)' is required.

这样用户就可以知道在哪里解决问题。

首先,我尝试了这个:

$attributes = [
  'img.*.file'    => 'Image file (item :* )',
  'img.*.alt'     => 'Image alt (item :* )',
  'img.*.caption' => 'Image caption (item :* )',
];
//
$this->validate($request, $rules, [], $attributes);

我认为:* 将被字段的索引(1、2、3、4 等)替换,就像:attribute 被属性替换一样。但是,:* 不会被字段的索引替换;相反,它显示为纯文本。

值得注意的是,我设计代码的方式是,HTML 名称属性按顺序为所有字段(img[1][alt][img][2][alt] 等、img[1][caption][img][2][caption] 等)编制索引,所以每个字段具有正确的索引。考虑到这一点,我想有一种方法可以获取索引并用于在错误消息中创建自定义属性。

我搜索了这个问题,在这里Validation on fields using index position找到了同样的问题,但是它使用了angular,而不是laravel

如何获取索引并将其放在attribute 中?如果不可能,是否有任何其他方法可以在无需设置错误消息的情况下实现理想的结果?

我想更改 attributes 并保留 laravel 提供的默认错误消息

【问题讨论】:

    标签: laravel validation


    【解决方案1】:

    试试这个例子

    $input = Request::all();
    
    $rules = array(
        'name' => 'required',
        'location' => 'required',
        'capacity' => 'required',
        'description' => 'required',
        'image' => 'required|array'
    );
    
    $validator = Validator::make($input, $rules);
    
    if ($validator->fails()) {
    
        $messages = $validator->messages();
    
        return Redirect::to('venue-add')
            ->withErrors($messages);
    
    }
    
    $imageRules = array(
        'image' => 'image|max:2000'
    );
    
    foreach($input['image'] as $image)
    {
        $image = array('image' => $image);
    
        $imageValidator = Validator::make($image, $imageRules);
    
        if ($imageValidator->fails()) {
    
            $messages = $imageValidator->messages();
    
            return Redirect::to('venue-add')
                ->withErrors($messages);
    
        }
    }
    

    【讨论】:

    • 我明白你的意思了!虽然你的代码没有解决问题,但它给了我一个解决问题的好主意!谢谢!
    【解决方案2】:

    感谢用户sss S,我可以实施他/她的想法来解决问题。

    这是store 方法的代码。它将错误消息中的(item) 替换为(item $i),其中$i 是该字段的索引。因此用户可以准确地知道错误在哪里。

    public function store(Request $request)
        {
            $rules      = $this->rules();
            $attributes = $this->attributes();
    
            $validator = Validator::make($request->all(), $rules, [], $attributes);
            $errors    = [];
    
            if ($validator->fails()) {
                $errors = $validator->errors()->all();
            }
    
    
            $imgRules = [
                'file'    => 'required|image|mimes:jpeg,jpg,webp,png|max:1999',
                'alt'     => 'required|string|max:100|min:5',
                'caption' => 'required|string|max:100|min:5',
            ];
    
            $imgAttributes = [
                'alt'     => 'HTML alt attribute (item)',
                'caption' => 'Caption(item)',
                'file'    => 'image file (item)',
            ];
    
            foreach($request->img as $i => $img) {
                $imgValidator = Validator::make($img, $imgRules, [], $imgAttributes);
                $imgErrors = [];
    
                if($imgValidator->fails()) {
                    $imgErrors = $imgValidator->errors()->all();
                }
    
                foreach($imgErrors as $k => $v) {
                    $imgErrors[$k] = str_replace('(item)', "(item $i)", $v);
                }
    
                $errors = array_merge($errors, $imgErrors);
            }
    
            if(count($errors) > 0) {
                return response()->json(['success' => false, 'errors' => $errors]);
            }
    
            // here is the code store the new resource
            //  ...
    
            // then return success message
        }
    
    

    【讨论】:

    • 老实说,这有点疯狂,必须以这种方式完成,而 laravel 没有类似 :num
    • 我同意你的看法。这是很多硬代码。 @Alex,你知道我可以在哪里向 Laravel 的新版本推荐一个功能吗?因此,也许它的新版本将具有用于验证动态字段的内置工具
    • 我猜官方 github。如果你这样做,我会添加评论以支持它!
    • @Alex 我确实向 Laravel 提出了功能请求。这是 [Github 上的问题] (github.com/laravel/framework/discussions/32977)。如果您添加评论以支持它,我将不胜感激
    猜你喜欢
    • 2020-09-20
    • 2013-11-05
    • 2020-02-13
    • 1970-01-01
    • 2018-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多