Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

adamjhn's avatar

How to show custom error messages without using $validator?

I have a form for a user register in a conference. The form has name and surname fields and can also have custom questions and I want to validate that in Laravel.

I had the validation like below but its not working properly. When the user clicks in the "Store Registration" button without fill all fields instead of remain on the same page and appear the validation errors the user is redirected to "http://proj.test/conference/1/conference-title/registration/storeRegistration" and it appears a blank page.

Validation with the issue:

 public function storeRegistration(Request $request, $id, $slug = null)
        $rules = [];
        $messages = [];
        $rules = [
            'participant.*.name' => 'required|string',
            'participant.*.surname' => 'required|string'
        ];

        if (isset($request->participant_question_required)) {
    
                $messages = [
                    'participant_question.*.required' => 'Fill all mandatory fields',
                ];
    
                foreach ($request->participant_question_required as $key => $value) {
                    $rule = 'string|max:255';
    
                    if ($value) {
                        $rule = 'required|' . $rule;
    
                    }
                    $rules["participant_question.{$key}"] = $rule;
    
                }
            }
        $validator = Validator::make($request->all(), $rules, $messages);
        ...
}

Using the code below it works, the validation errors appear if the user dont answer all required fields. But like below do you know how to show custom validation messages? So that, when the user dont answer a custom question, instead of appear "The participant.1.answer field is required." appear "Please fill all required custom questions."

public function storeRegistration(Request $request, $id, $slug = null)
    {

        $this->validate($request, [
            'participant.*.name' => 'required|string',
            'participant.*.surname' => 'required|string',
        ]);

        if (isset($request->participant_question_required)) {

            $messages = [
                'participant_question.*.required' => 'Fill all mandatory fields',
            ];

            foreach ($request->participant_question_required as $key => $value) {

                if ($value) {
                    $this->validate($request, [
                        'participant.*.answer' => 'required',
                    ]);
                }
            }
        }
        ...
    }
0 likes
8 replies
Cronix's avatar
Cronix
Best Answer
Level 67

You'd need to make a rule for it so that the error message can show if there is one. If there isn't a rule for it, the error message for that rule would never get triggered since it didn't actually run through validation, so it can't fail the validation which creates the errors.

$this->validate($request, [
    'participant.*.name' => 'required|string',
    'participant.*.surname' => 'required|string',
    'participant_question.*.required' => 'required'
]);

additionally, this doesn't make sense

foreach ($request->participant_question_required as $key => $value) {

                if ($value) {
                    $this->validate($request, [
                        'participant.*.answer' => 'required',
                    ]);
                }
            }

You're adding the exact same rule over and over, which uses a *, which means it only needs to be added once since * means for all participant[]answers, not an individual one.

If you're trying to target specific elements in the array, then you'd add the index ($key) to the rule instead of *.

"participant.{$key}.answer" => 'required',
1 like
Cronix's avatar

Edit: you might be able to make a custom error without a rule using the after validation hook. I haven't tried it for that. See the docs for validation.

You can also just set a session variable if there's an error, and check it in the view. Or just use a regular variable. That doesn't have anything to do with validation though. Just like passing a normal variable to a view, and checking if it exists and displaying it if it does.

1 like
adamjhn's avatar

Thanks, creating a rule, that is a custom validation rule? Like "php artisan make:rule ValidateRegistrationForm"?

Cronix's avatar

Did you read the docs for "after validation hook"?

What's wrong with setting a simple session flash variable and showing it in the view?

if (yourConditions) {
    $request->session()->flash('participant_question_required', 'Fill all mandatory fields');
}
@if (session('participant_question_required'))
    {{ session('participant_question_required') }}
@endif

That will show a custom message without using the validator, like you wanted.

1 like
adamjhn's avatar

Thanks, but using sessions is possible to reuse the errors.blade.php file that shows the errors? I have the include of the errors.blade.php above the tag, and the file is like:

@if ($errors->any())
    <div class="alert alert-danger mt-3">
        <ul>
            @foreach ($errors->all() as $error)
                <li class="text-danger">{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

I was testing that with the code below but if a required field is not answered it appears always a sql error saying that the name, surname or answer cannot be null:


    $rules = [];
    $messages = [];
    $rules = [
        'participant.*.name' => 'required|string',
        'participant.*.surname' => 'required|string'
    ];

    if (isset($request->participant_question_required)) {

        $messages = [
            'participant_question.*.required' => 'Fill all mandatory fields',
        ];

        foreach ($request->participant_question_required as $key => $value) {
            $rule = 'string|max:255';

            if ($value) {
                $rule = 'required|' . $rule;

            }
            $rules["participant_question.{$key}"] = $rule;

        }
    }
    $validator = Validator::make($request->all(), $rules, $messages);

    //dd($request->all(), $rules);

    $validator->after(function ($validator) {
        dd('test');
        if ($this->somethingElseIsInvalid()) {
            $validator->errors()->add('field', 'Something is wrong with this field!');
        }
    });

And $request->all() and $rules shows:

array:3 [▼
  "_token" => ""
  "participant" => array:1 [▼
    1 => array:5 [▼
      "name" => "rere"
      "surname" => "re"
      "answer" => null
      "question_id" => "1"
      "rtypes" => "1"
    ]
  ]
  "participant_question_required" => array:1 [▼
    0 => "1"
  ]
]
array:3 [▼
  "participant.*.name" => "required|string"
  "participant.*.surname" => "required|string"
  "participant_question.0" => "required|string|max:255"
]
]
Cronix's avatar

I really don't understand why you're trying to do things the way you are. You want to validate it, but not go though the validator. So if you don't go through the validator, of course you can't use the same template to display the errors because it's not a validation error using $validator.

Then you say the fields can't be null. Ok, so it sounds like it really should be a regular rule so that they have to fill out the required fields. The validator needs to fail the rule, so that it doesn't successfully get past validation and try to save the data with nulls.

adamjhn's avatar

Thanks, and sorry maybe I didnt explain well. I would like to use $validator like below. The issue is that like below, as it is in the question, when the user clicks in the "Store Registration" button without fill all required fields the user is redirected to "http://proj.test/conference/1/conference-title/registration/storeRegistration" and it appears a blank page instead of remain on the same page and the validaton errors appear.

 public function storeRegistration(Request $request, $id, $slug = null)
        $rules = [];
        $messages = [];
        $rules = [
            'participant.*.name' => 'required|string',
            'participant.*.surname' => 'required|string'
        ];

        if (isset($request->participant_question_required)) {
    
                $messages = [
                    'participant_question.*.required' => 'Fill all mandatory fields',
                ];
    
                foreach ($request->participant_question_required as $key => $value) {
                    $rule = 'string|max:255';
    
                    if ($value) {
                        $rule = 'required|' . $rule;
    
                    }
                    $rules["participant_question.{$key}"] = $rule;
    
                }
            }
        $validator = Validator::make($request->all(), $rules, $messages);
        ...
}

So, I checked this approach below to verify if the same issue happens and with this approach the issue dont happen, the user is not redirected to another page and the errors appear. But then I would like to know if with this approach, since it works, how to properly show custom messages:

$this->validate($request, [
            'participant.*.name' => 'required|string',
            'participant.*.surname' => 'required|string',
        ]);

if (isset($request->participant_question_required)) {



            $messages = [
                'participant_question.*.required' => 'Fill all mandatory fields',
            ];

            foreach ($request->participant_question_required as $key => $value) {
                $rule = 'string|max:255';

                if ($value) {
                    $this->validate($request, [
                        'participant.*.answer' => 'required',
                    ]);

                }
                $rules["participant_question.{$key}"] = $rule;

            }
 }

Cronix's avatar

Now we're back to my first post. You can't show validation errors for fields that aren't in the $rules.

You set a custom message here for the participant_question field

$messages = [
                    'participant_question.*.required' => 'Fill all mandatory fields',
                ];

but don't have a $rule to trigger it, like you do here:

$this->validate($request, [
            'participant.*.name' => 'required|string',
            'participant.*.surname' => 'required|string',
        ]);

So, it's totally ignored.

1 like

Please or to participate in this conversation.