Saturday, May 5, 2018

How to properly store the necessary info to register the user and other participants in the congress? (scenario 1 works but scenario 2 and 3 dont)

Leave a Comment

I have a congress registration page that has the form below that the user should fill to register in the congress. In this registration form:

  • If "all_participants" column is "1" in the congress table, it appears for each selected ticket in the previous page (congress details page) a section for the user that is doing the registration insert the name and surname of each participant (that is, associating each selected ticket in the previous page to a participant name and surname)

  • If the all_participants column is "0", it appears the "<p>Is not necessary additional info.</p>" because is not necessary to collect info of each participant (for each selected ticket). The registration is done using the information of the authenticated user.

  • the selected tickets from the previous page are available in the variable "$selectedTypes"

// registration form in the registration.blade.php page

      <form method="post" id="step1form" action="">     {{csrf_field()}}     @if (!empty($allParticipants))         @if($allParticipants == 1)             <p>Please fill in all fields. Your tickets will be sent to                 p{{ (\Auth::check()) ? Auth::user()->email : old('email')}}.</p>              @foreach($selectedTypes as $selectedType)                 @foreach(range(1,$selectedType['quantity']) as $test)                      <h6>Participant - 1 - {{$test}}</h6>                     <div class="form-check">                         <input class="form-check-input" type="radio" name="payment_method" value="referencias">                         <label class="form-check-label d-flex align-items-center" for="exampleRadios1">                             <span class="mr-auto">Fill the following fields with the authenticated user information.</span>                         </label>                     </div>                     <div class="form-group font-size-sm">                         <label for="participant_name" class="text-gray">Name</label>                         <input type="text" name="participant_name[]" required class="form-control" value="">                     </div>                     <div class="form-group font-size-sm">                         <label for="participant_surname" class="text-gray">Surname</label>                         <input type="text" required class="form-control" name="participant_surname[]" value="">                     </div>                     <input type="hidden" name="ttypes[]" value="{{ $selectedType['id'] }}"/>                     @foreach($selectedType['questions'] as $customQuestion)                         <div class="form-group">                             <label for="participant_question">{{$customQuestion->question}}</label>                             <input type="text"                                    @if($customQuestion->pivot->required == "1") required @endif                                    class="form-control" name="participant_question[]">                             <input type="hidden" name="participant_question_required[]"                                    value="{{ $customQuestion->pivot->required }}">                             <input type="hidden" value="{{ $customQuestion->id }}" name="participant_question_id[]"/>                         </div>                     @endforeach                 @endforeach             @endforeach             @else                 <p>Its not necessary aditional info. Your tickets will be sent to {{ (\Auth::check()) ? Auth::user()->email : old('email')}}.</p>              @endif         @endif      <input type="submit" href="#step2"            id="goToStep2Free" class="btn btn-primary btn float-right next-step" value="Go to step 2"/> </form> 

Issues: For the user register in the conference can exist 3 scenarios. The first scenario is working fine, Im getting issues in the scenario 2 and 3.

Scenario 1 is working fine: "all_participants" column is "1" in the congresses table which means that is necessary to collect info of each participant and the user selected in the previous page (congress details page) 1 or more ticket types that have asociated one or more custom questions. This is the only scenario that is working fine. Diagram demonstrating the scenario:

enter image description here

This is working fine. The registrations and participants table stay like:

Registration table

id  congress_id     main_participant_id 1        1                   1            (user 1 registers in the congress with id 1) 

Participants table

id     registration_id     ticket_type_id       name     surname 1            1                     1             John       X 2            1                     2             Jake       Y 

Answers table

id     participant_id     question_id       answer      1            1                     1          000        

Questions table

id           question                        congress_id       answer      1          Whats your phone?                    1              000        

Scenario 2 is not working fine The scenario 2 is If all_participants is "1" and the user select ticket types that dont have any no custom questions associated. In this scenario Im getting this error below because "$request->participant_question_required" dont exist:

 "Invalid argument supplied for foreach()" in          ...         else {             $messages = [                 'participant_question.*.required' => 'The participant is required'             ];             foreach ($request->participant_question_required as $key => $value) {         ... 

I can put "if(isset($request->participant_question_required)) {" and then all code inside of this, but like that if the congress dont have any custom question associated then dont appears any error but no record are inserted in the registrations and participants table.

Diagram of the scenario 2 to demonstrate the issue:

enter image description here

Scenario 3 is not working fine: If all_participants is "0" and the user select ticket types that have 1 or more custom questions associated, in the registartion form dont appears any custom question. But if there are custom questions for some ticket type selected by the user and "all_participant" is "0" which means that is only necessary to collect info from the user that is doing the registration (the authenticated user) it shoud appear the custom question(s) associated to the selected ticket type(s) for the user that is doing the registration to answer.

Diagram of the scenario 3 to demonstrate the issue:

enter image description here

// complete method to register the user in the congress

public function StoreUserInfo(Request $request, $id, $slug = null, Validator $validator){     $allParticipants = Congress::where('id', $id)->first()->all_participants;     $user = Auth::user();      if($allParticipants){         $rules = [             'participant_name.*' => 'required|max:255|string',             'participant_surname.*' => 'required|max:255|string',         ];          $messages = [             'participant_question.*.required' => 'The participant is required'         ];          foreach ($request->participant_question_required as $key => $value) {             $rule = 'string|max:255'; // I think string should come before max             //dd($value);             // if this was required, ie 1, prepend "required|" to the rule             if ($value) {                 $rule = 'required|' . $rule;             }              // add the individual rule for this array key to the $rules array             $rules["participant_question.{$key}"] = $rule;         }          $validator = Validator::make($request->all(), $rules, $messages);          if($validator->passes()) {             $registration = Registration::create([                 'congress_id' => $id,                 'main_participant_id' => $user->id,                 'status' => 'C',             ]);              $participants = [];              for ($i = 0; $i < count($request->participant_name); $i++)                 $participants[] = Participant::create([                     'name' => $request->participant_name[$i],                     'surname' => $request->participant_surname[$i],                     'registration_id' => $registration->id,                     'ticket_type_id' => $request->rtypes[$i]                  ]);              for ($i = 0; $i < count($request->participant_question); $i++)                 $answer = Answer::create([                     'question_id' => $request->participant_question_id[$i],                     'participant_id' => $participants[$i]->id,                     'answer' => $request->participant_question[$i],                 ]);             }          return response()->json([             'success' => true,             'message' => 'success'         ], 200);     }       else {          $messages = [             'participant_question.*.required' => 'The participant is required'         ];           foreach ($request->participant_question_required as $key => $value) {             $rule = 'string|max:255'; // I think string should come before max             //dd($value);             // if this was required, ie 1, prepend "required|" to the rule             if ($value) {                 $rule = 'required|' . $rule;             }              // add the individual rule for this array key to the $rules array             $rules["participant_question.{$key}"] = $rule;         }           $validator = Validator::make($request->all(), $rules, $messages);           if ($validator->passes()) {              $registration = Registration::create([                 'congress_id' => $id,                 'main_participant_id' => $user->id,                 'status' => 'C',              ]);              $participants = [];              for ($i = 0; $i < count($request->participant_name); $i++)                 $participants[] = Participant::create([                     'name' => '',                     'surname' => '',                     'registration_id' => $registration->id,                     'ticket_type_id' => $request->rtypes[$i]                  ]);              for ($i = 0; $i < count($request->participant_question); $i++)                 $answer = Answer::create([                     'question_id' => $request->participant_question_id[$i],                     'participant_id' => $participants[$i]->id,                     'answer' => $request->participant_question[$i],                 ]);         }          return response()->json([             'success' => true,             'message' => 'success'         ], 200);      } } 

Relevant models to the question:

class Congress extends Model {     // A conference has many ticket types     public function ticketTypes(){         return $this->hasMany('App\TicketType', 'congress_id');     }      public function registrations(){         return $this->hasMany('App\Registration', 'congress_id');     } }  // RegistrationModel class Registration extends Model {     // a registration has one user that do the registration (main_participant_id)     public function customer(){         return $this->belongsTo('App\User');     }     public function congress(){         return $this->belongsTo('App\Congress');     } }  class TicketType extends Model {     public function congress(){         return $this->belongsTo('App\Congress');     } }  class Question extends Model {     public function registration_type(){         return $this->belongsToMany('App\RegistrationType', 'ticket_type_questions')             ->withPivot('required');     } }  class Answer extends Model {     public function question(){         return $this->belongsTo('Question');     }     public function participant(){         return $this->belongsTo('Participant');     } } 

3 Answers

Answers 1

If you wish to store more than one ticket_type to a participant you will need to use a pivot table. A pivot table is a table that only contains ids and relates data together in a many to many fashion.

e.g.

participants_ticket_type table id      ticket_type_id   participant_id 1          1               2 2          2               2 

Notice how participant 2 has ticket_types of 1 and 2? This is a many to many relationship.

Laravel handles these relationships for you and you can find it in their docs. https://laravel.com/docs/5.6/eloquent-relationships#many-to-many

Usually if you find yourself storing more than 1 id in a column a many to many relationship will solve this issue.

Answers 2

I see two things

1.- The form doesn't send anything when $allParticipants == 0, maybe something more like:

    <form method="post" id="step1form" action="">     {{csrf_field()}}     @if (!is_null($allParticipants) && is_int($allParticipants))         @if($allParticipants == 1)                <p>Please fill in all fields. Your tickets will be sent to                 p{{ (\Auth::check()) ? Auth::user()->email : old('email')}}.</p>         @else             <p>Its not necessary aditional info. Your tickets will be sent to {{ (\Auth::check()) ? Auth::user()->email : old('email')}}.</p>         @endif          @foreach($selectedTypes as $selectedType)             @foreach(range(1,$selectedType['quantity']) as $test)                 <h6>Participant - 1 - {{$test}}</h6>                 <div class="form-check">                     <input class="form-check-input" type="radio" name="payment_method" value="referencias">                     <label class="form-check-label d-flex align-items-center" for="exampleRadios1">                         <span class="mr-auto">Fill the following fields with the authenticated user information.</span>                     </label>                 </div>                 @if($allParticipants == 1)                     <div class="form-group font-size-sm">                         <label for="participant_name" class="text-gray">Name</label>                         <input type="text" name="participant_name[]" required class="form-control" value="">                     </div>                     <div class="form-group font-size-sm">                         <label for="participant_surname" class="text-gray">Surname</label>                         <input type="text" required class="form-control" name="participant_surname[]" value="">                     </div>                    @foreach($selectedType['questions'] as $customQuestion)                     <div class="form-group">                         <label for="participant_question">{{$customQuestion->question}}</label>                         <input type="text"                                 @if($customQuestion->pivot->required == "1") required @endif                                 class="form-control" name="participant_question[]">                         <input type="hidden" name="participant_question_required[]"                                 value="{{ $customQuestion->pivot->required }}">                         <input type="hidden" value="{{ $customQuestion->id }}" name="participant_question_id[]"/>                     </div>                    @endforeach                 @else                     <input type="hidden" value="foo" name="participant_name[]"/>                     <input type="hidden" value="bar" name="participant_surname[]"/>                 @endif                 <input type="hidden" name="ttypes[]" value="{{ $selectedType['id'] }}"/>                             @endforeach             @if ($allParticipants == 0)                @foreach($selectedType['questions'] as $customQuestion)                     <div class="form-group">                         <label for="participant_question">{{$customQuestion->question}}</label>                         <input type="text"                                 @if($customQuestion->pivot->required == "1") required @endif                                 class="form-control" name="participant_question[]">                         <input type="hidden" name="participant_question_required[]"                                 value="{{ $customQuestion->pivot->required }}">                         <input type="hidden" value="{{ $customQuestion->id }}" name="participant_question_id[]"/>                     </div>                 @endforeach             @endif         @endforeach     @endif      <input type="submit" href="#step2"             id="goToStep2Free" class="btn btn-primary btn float-right next-step" value="Go to step 2"/>     </form> 

2.- Questions seems to depend on Ticket types and are optionals, the function should take it into account.

public function StoreUserInfo(Request $request, $id, $slug = null, Validator $validator){     $allParticipants = Congress::where('id', $id)->first()->all_participants;     $user = Auth::user();      $rules = [];     $messages = [];      if(isset($request->participant_question_required)) {         $messages = [             'participant_question.*.required' => 'The participant is required'         ];          foreach ($request->participant_question_required as $key => $value) {             $rule = 'string|max:255'; // I think string should come before max             //dd($value);             // if this was required, ie 1, prepend "required|" to the rule             if ($value) {                 $rule = 'required|' . $rule;             }              // add the individual rule for this array key to the $rules array             $rules["participant_question.{$key}"] = $rule;         }     }      if($allParticipants){         $rules = [             'participant_name.*' => 'required|max:255|string',             'participant_surname.*' => 'required|max:255|string',         ];     }      $validator = Validator::make($request->all(), $rules, $messages);      if($validator->passes()) {         $registration = Registration::create([             'congress_id' => $id,             'main_participant_id' => $user->id,             'status' => 'C',         ]);          $participants = [];         for ($i = 0; $i < count($request->participant_name); $i++) {             $name = ($allParticipants) ? $request->participant_name[$i] : '';             $surname = ($allParticipants) ? $request->participant_surname[$i] : '';             $participants[] = Participant::create([                 'name' => $name,                 'surname' => $surname,                 'registration_id' => $registration->id,                 'ticket_type_id' => $request->rtypes[$i]              ]);         }          if (isset($request->participant_question))             for ($i = 0; $i < count($request->participant_question); $i++)                     $answer = Answer::create([                         'question_id' => $request->participant_question_id[$i],                         'participant_id' => $participants[$i]->id,                         'answer' => $request->participant_question[$i],                     ]);     }      return response()->json([         'success' => true,         'message' => 'success'     ], 200); } 

Hope it works! Regards

Answers 3

First of all use select * from TABLENAME and then use the COUNT function either in the query Or use PHP Count function on the laravel blade file then execute your code..

on blade file

@if(count($records)>0){    // Your Code  } 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment