Laravel custom messages for array validation

后端 未结 10 2482
南笙
南笙 2021-02-20 05:36

I am having a form and I have an array of input fields for video urls, now when I validate form if I have multiple invalid fields with video urls, I get the same message for eac

10条回答
  •  不要未来只要你来
    2021-02-20 06:15

    Edit with potential solution

    After some digging around, I've had a look at the Validator class and how it is adding it's error messages to see if it has any available placeholders.

    In the Illuminate\Validation\Validator the function that I think is run to validate a request is validate, which runs each of the rules in turn and adds error messages. The piece of code related to adding an error message is this one, at the end of the function:

        $value = $this->getValue($attribute);
    
        $validatable = $this->isValidatable($rule, $attribute, $value);
    
        $method = "validate{$rule}";
    
        if ($validatable && ! $this->$method($attribute, $value, $parameters, $this)) {
            $this->addFailure($attribute, $rule, $parameters);
        }
    

    As you can see, it's not actually passing the value of the field that was validated through when it's adding a failure, which in turn adds an error message.

    I've managed to get something working to achieve what you're after. If you add these two methods into your base Request class which is usually at App\Http\Requests\Request:

    protected function formatErrors(Validator $validator)
    {
        $errors = parent::formatErrors($validator);
    
        foreach ($errors as $attribute => $eachError) {
            foreach ($eachError as $key => $error) {
                if (strpos($error, ':value') !== false) {
                    $errors[$attribute][$key] = str_replace(':value', $this->getValueByAttribute($attribute), $error);
                }
            }
        }
    
        return $errors;
    }
    
    protected function getValueByAttribute($attribute)
    {
        if (($dotPosition = strpos($attribute, '.')) !== false) {
            $name = substr($attribute, 0, $dotPosition);
            $index = substr($attribute, $dotPosition + 1);
    
            return $this->get($name)[$index];
        }
    
        return $this->get($attribute);
    }
    

    Then in your validation messages you should be able to put the :value replacer, which should be replaced with the actual value that was validated, like this:

    public function messages()
    {
        return [
            'external_media.*.active_url' => 'The URL :value is not valid'
        ];
    }
    

    I've noticed a couple of problems with your code:

    • In your messages function you've provided a message for active_url which is the name of the rule, rather than the name of the field. This should be external_media.
    • You're not returning the $messages variable from your messages function. You need to add return $messages; to the end.

    With regards to your question however, the class in which you write this code is an instance of Illuminate\Http\Request and you should be able to access the actual values provided to that request when generating your error messages. For example, you could do something like this:

    public function messages()
    {
        return [
            'external_media' => 'The following URL is invalid: ' . $this->get('external_media')
        ];
    }
    
    public function rules()
    {
        return [
            'external_media' => 'active_url'
        ];
    }
    

    Which would include the value provided to external_media in the error message. Hope this helps.

提交回复
热议问题