Why the validation is not working properly?

Published 1 month ago by adamjhn

I have the form below for a user register in a conference. The form can have custom questions, in this case, it has the custom question "Phone" and is a required question so I want to validate that in Laravel. The name and surname fields should also be required.

But the validation it´s not working properly, even if the "required" attribute is removed from the source code and the "Store Registration" button is clicked the code never enters in "`if ($validator->passes()) {...".

Do you know why the validation is not working?

storeRegistration():




     public function storeRegistration(Request $request, $id, $slug = null)
        {
            
            $rules = [];
            $messages = [];
    
            $rules["participant_name.*"] = 'required|max:255|string';
            $rules["participant_surname.*"] = 'required|max:255|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);
    
    
            if ($validator->passes()) {
    
                dd('test');
    
                $total = Session::get('total');
    
                # user object
                $user = Auth::user();
    
                $registration = Registration::create([
                    'conference_id' => $id,
                    'main_participant_id' => $user->id,
                    'status' => ($total > 0) ? 'I' : 'C',
                ]);
    
                $participants_list = $request->get('participant');
    
                foreach ($participants_list as $participant) {
                    $name = $participant['name'];
                    $surname = $participant['surname'];
                    $participant_result = Participant::create([
                        'name' => $name,
                        'surname' => $surname,
                        'registration_id' => $registration->id,
                        'registration_type_id' => $participant['rtypes']
                    ]);
    
                    if (isset($participant['question_id'])) {
                        $answer = Answer::create([
                            'question_id' => $participant['question_id'],
                            'participant_id' => $participant_result->id,
                            'answer' => $participant['answer'],
                        ]);
                    }
                }
                return redirect(route('user.index', ['user' => Auth::id()]) . '#myTickets');
            } else {
                dd($validator->errors());
            }
        }

The "dd($validator->errors());" shows:


    MessageBag {#271 ▼
      #messages: array:2 [▼
        "participant_question.0" => array:1 [▼
          0 => "FIll all mandatory fields"
        ]
        "participant_question.1" => array:1 [▼
          0 => "Fill all mandatory fields"
        ]
      ]
      #format: ":message"
    }

Form for the user to register in a conference:


    <form method="post" id="registration_form" action="">
      <input type="hidden" name="_token" value="">        
    
      <h6 > Participant - 1 - geral</h6>    
    
      <div class="form-group font-size-sm">
        <label for="namegeral_1" class="text-gray">Name</label>
        <input type="text" id="namegeral_1" name="participant[1][name]" required="" class="form-control" value="">
      </div>
      
      <div class="form-group font-size-sm">
        <label for="surnamegeral_1" class="text-gray">Surname</label>
        <input type="text" id="surnamegeral_1" required="" class="form-control" name="participant[1][surname]" value="">
      </div>
    
      <div class="form-group">
        <label for="participant_question">Phone?</label>
        <input type="text" name="participant[1][answer]" class="form-control" required="">
        <input type="hidden" name="participant_question_required[]" value="1">
        <input type="hidden" value="1" name="participant[1][question_id]">
      </div>
    
      <input type="hidden" name="participant[1][rtypes]" value="1">
    
      <h6> Participant - 2 - geral</h6>
    
      <div class="form-group font-size-sm">
        <label for="namegeral_2" class="text-gray">Name</label>
        <input type="text" id="namegeral_2" name="participant[2][name]" required="" class="form-control" value="">
      </div>
      
      <div class="form-group font-size-sm">
        <label for="surnamegeral_2" class="text-gray">Surname</label>
        <input type="text" id="surnamegeral_2" required="" class="form-control" name="participant[2][surname]" value="">
      </div>
    
      <div class="form-group">
        <label for="participant_question">Phone?</label>
        <input type="text" name="participant[2][answer]" class="form-control" required="">
        <input type="hidden" name="participant_question_required[]" value="1">
        <input type="hidden" value="1" name="participant[2][question_id]">
      </div>
    
      <input type="hidden" name="participant[2][rtypes]" value="1">
    
    
      <h6> Participant - 3 - plus</h6>    
    
      <div class="form-group font-size-sm">
        <label for="nameplus_3" class="text-gray">Name</label>
        <input type="text" id="nameplus_3" name="participant[3][name]" required="" class="form-control" value="">
      </div>
      <div class="form-group font-size-sm">
        <label for="surnameplus_3" class="text-gray">Surname</label>
        <input type="text" id="surnameplus_3" required="" class="form-control" name="participant[3][surname]" value="">
      </div>
    
      <input type="hidden" name="participant[3][rtypes]" value="2">
      <input type="submit" class="btn btn-primary" value="Store Registration">
    </form>

Snapey
Snapey
1 month ago (929,875 XP)

insert a dd() so that you can validate data and rules

    $validator = Validator::make($request->all(), $rules, $messages);
    
    dd($request->all(), $rules);
    
    if ($validator->passes()) {
   
adamjhn

Thanks, that shows, based on the fields filled by the user on the form:


array:4 [▼
  "_token" => ""
  "participant" => array:3 [▼
    1 => array:5 [▼
      "name" => "John"
      "surname" => null
      "answer" => null
      "question_id" => "1"
      "rtypes" => "1"
    ]
    2 => array:5 [▼
      "name" => "ere"
      "surname" => "ere"
      "answer" => "003"
      "question_id" => "1"
      "rtypes" => "1"
    ]
    3 => array:3 [▼
      "name" => "i"
      "surname" => "i"
      "rtypes" => "2"
    ]
  ]
  "participant_question_required" => array:2 [▼
    0 => "1"
    1 => "1"
  ]
]
array:4 [▼
  "participant_name.*" => "required|string"
  "participant_surname.*" => "required|string"
  "participant_question.0" => "required|string|max:255"
  "participant_question.1" => "required|string|max:255"
]


Snapey
Snapey
1 month ago (929,875 XP)

can you see the issue? you dont have ANY of the fields mentioned in your rules

adamjhn

Thanks! But same error defining the rules for the participants array like::

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

Try

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

Also dont work with:

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

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

array:3 [▼
  "_token" => ""
  "participant" => array:2 [▼
    1 => array:5 [▼
      "name" => "rere"
      "surname" => "r"
      "answer" => "0003"
      "question_id" => "1"
      "rtypes" => "1"
    ]
    2 => array:3 [▼
      "name" => null
      "surname" => null
      "rtypes" => "2"
    ]
  ]
  "participant_question_required" => array:1 [▼
    0 => "1"
  ]
]
array:2 [▼
  "participant.*.name" => "required|string"
  "participant.*.surname" => "required|string"
]

Snapey
Snapey
1 month ago (929,875 XP)

your later post looks more correct, but the second participant is null so I would expect that to throw a validation exception

adamjhn

Thanks, is null because the "required" was removed from the source code and no value was introduced for the name and surname for the second participant so the validation errors should appear with " @include('includes.errors') " but dont appear, it appears a blank page. And with " //dd($validator->errors());" uncommented it shows:

MessageBag {#271 ▼
  #messages: array:2 [▼
    "participant.2.name" => array:1 [▼
      0 => "The participant.2.name field is required."
    ]
    "participant.2.surname" => array:1 [▼
      0 => "The participant.2.surname field is required."
    ]
  ]
  #format: ":message"
}

Snapey
Snapey
1 month ago (929,875 XP)

so message bag contains the correct messages

what logic do you have to decide if to show the errors view?

adamjhn

The errors.blade.php file have this content:

@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

And its used above the registration form like:


 @include('includes.errors')
            <form method="post"
                  action="{{route('conferences.storeRegistration', ['id' => $id, 'slug' => $slug])}}">
                {{csrf_field()}}

Complete storeRegistration():

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

    $rules = [];
    $messages = [];

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

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

    if ($validator->passes()) {

        dd('test');

        $total = Session::get('total');

        # user object
        $user = Auth::user();

        # add registration to Database
        $registration = Registration::create([
            'conference_id' => $id,
            'main_participant_id' => $user->id,
            'status' => ($total > 0) ? 'I' : 'C',
        ]);

        # List of all participants
        $participants_list = $request->get('participant');

        #add all participants to Database
        foreach ($participants_list as $participant) {
            $name = $participant['name'];
            $surname = $participant['surname'];
            $participant_result = Participant::create([
                'name' => $name,
                'surname' => $surname,
                'registration_id' => $registration->id,
                'registration_type_id' => $participant['rtypes']
            ]);

            # save answer to Database if exist
            if (isset($participant['question_id'])) {
                $answer = Answer::create([
                    'question_id' => $participant['question_id'],
                    'participant_id' => $participant_result->id,
                    'answer' => $participant['answer'],
                ]);
            }
        }
        //return redirect(route('user.index', ['user' => Auth::id()]) . '#myTickets');
    } else {
        //dd($validator->errors());
    }
}
Snapey
Snapey
1 month ago (929,875 XP)

because you validate arrays, you have to iterate over the elements in each message

change to this so that you can see

@if ($errors->any())
    <div class="alert alert-danger mt-3">
        <ul>
            @foreach ($errors->all() as $error)
                <?php dump($error); ?>
            @endforeach
        </ul>
    </div>
@endif



adamjhn

Thanks, but also dont appear any error.

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.

Snapey
Snapey
1 month ago (929,875 XP)

what is in the address bar before the user presses submit

(exact answer please)

adamjhn

Its "http://proj.test/conference/1/conference-title/registration". Its the page with the form to store the registration.

Snapey
Snapey
1 month ago (929,875 XP)

its just that your form action="" which means that the form is posted to the same URL so I dont understand how the user ends up at storeRegistration

Please sign in or create an account to participate in this conversation.