Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to organize this context to collect properly the answers of each participant?

Tags:

php

laravel

I have a form for a user register in a conference. But when the user clicks in "Store Registration" it shows an undefined offset error and the issue should be because I'm not organizing correctly this context. The form to register in a conference is different depending on if the "all_participants" column of the conferences table is "1" or "0".

If all_participants is 1 in the conferences table

If the conferences table has the column "all_participants" with value "1" that means that is necessary to collect the name and surname of each participant (about each selected registration type). So the form will show form fields to collect the name and surname of each participant. Also if some of the selected registration type(s) have custom questions associated is necessary to collect the answers to that questions for each participant if "all_participants" is 1. In the image above the registration type "General" has a custom question associated "Phone", so its necessary to collect the answers of the two participants there are being registered with the registration type "General".

Image that shows the form of all_participants as "1" in the conferences table

enter image description here

After the user click in "Store Registration" it should be stored in the tables like below:

enter image description here

If all_participants is 0 in the conferences table

If "all_participants" is "0" the form would have only one field "Phone" because the name and surname are got directly from the authenticated user info. And because "all_participants" is "0" is only necessary also to collect the phone of the user that is doing the registration (the authenticated user), for the other participants is not necessary because "all_participants" is "0". So the form if "all_participants" is "0" would have only one field (Phone) in this case. And the participants table is only necessary to store the name and surname of the user that did the registration, for the other participants can be stored empty "".

Form if all_participants is "0":

enter image description here

After the user click in "Store Registration" it should be stored in the tables like below:

enter image description here

HTML of this image context for the case of "all_participants" is 1:

<form method="post" id="registration_form" action="http://proj.test/conference/1/conference-title/registration/storeRegistration">

  <h6>Participant - 1 - general</h6>
  <div class="form-group">
    <label for="namegeneral_1">Name</label>
    <input type="text" id="namegeneral_1" name="participant_name[]" required="" class="form-control" value="">
  </div>

  <div class="form-group">
    <label for="surnamegeneral_1">Surname</label>
    <input type="text" id="surnamegeneral_1" required="" class="form-control" name="participant_surname[]" value="">
  </div>

  <div class="form-group">
    <label for="participant_question">Phone?</label>
    <input type="text" name="participant_question[]" class="form-control" required="">
    <input type="hidden" name="participant_question_required[]" value="1">
    <input type="hidden" value="1" name="participant_question_id[]">
  </div>

  <input type="hidden" name="rtypes[]" value="1">

  <h6> Participant - 2 - general</h6>

  <div class="form-group">
    <label for="namegeneral_2">Name</label>
    <input type="text" id="namegeneral_2" name="participant_name[]" required="" class="form-control" value="">
  </div>

  <div class="form-group">
    <label for="surnamegeneral_2">Surname</label>
    <input type="text" id="surnamegeneral_2" required="" class="form-control" name="participant_surname[]" value="">
  </div>

  <div class="form-group">
    <label for="participant_question">Phone?</label>
    <input type="text" name="participant_question[]" class="form-control" required="">
    <input type="hidden" name="participant_question_required[]" value="1">
    <input type="hidden" value="1" name="participant_question_id[]">
  </div>

  <input type="hidden" name="rtypes[]" value="1">

  <h6> Participant - 1 - plus</h6>

  <div class="form-group font-size-sm">
    <label for="nameplus_1">Name</label>
    <input type="text" id="nameplus_1" name="participant_name[]" required="" class="form-control" value="">
  </div>

  <div class="form-group font-size-sm">
    <label for="surnameplus_1">Surname</label>
    <input type="text" id="surnameplus_1" required="" class="form-control" name="participant_surname[]" value="">
  </div>

  <input type="hidden" name="rtypes[]" value="2">

  <input type="submit" class="btn btn-primary" value="Store Registration">
</form>

When user clicks in "Store Registration" the code goes to the StoreRegistration() to store all the registration info in database:

public function storeRegistration(Request $request, $id, $slug = null)
  {
      $allParticipants = Conference::where('id', $id)->first()->all_participants;
      $user = Auth::user();

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

      if ($allParticipants == 1) {

          $rules["participant_name.*"] = 'required|max:255|string';
          $rules["participant_surname.*"] = 'required|max:255|string';
      }

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

      if ($validator->passes()) {

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

          $registration = Registration::create([
              'conferenec_id' => $id,
              'main_participant_id' => $user->id,
              'status' => ($total > 0) ? 'I' : '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,
                  'registration_type_id' => $request->rtypes[$i]

              ]);
          }

          if (isset($request->participant_question)) {
              foreach( $request->participant_question as $key => $question ) {
                  $answer = Answer::create([
                      'question_id' => $request->participant_question_id[$key],
                      'participant_id' => $participants[$key]->id, // undefined index error is here
                      'answer' => $request->participant_question[$key],
                  ]);
              }
          }
          return redirect(route('user.index', ['user' => Auth::id()]).'#myTickets');
      }
      else{
          dd($validator->errors());
      }
  }

I have the Question model that has the getHtmlInput() to generate the HTML for the custom questions and add the required attribute to the field if the "required" column in pivot table "registration_type_questions" is "1":

class Question extends Model
{
    protected $fillable = [
        'question', 'type', 'conference_id',
    ];
    public static $typeHasOptions = [
        'radio_btn',
        'select_menu',
        'checkbox'
    ];
    public function registration_type()
    {
        return $this->belongsToMany('App\RegistrationType', 'registration_type_questions')
            ->withPivot('required');
    }
    public function options()
    {
        return $this->hasMany('App\QuestionOption');
    }
    public function hasOptions()
    {
        return in_array($this->type, self::$typeHasOptions);
    }
    public function getHtmlInput($name = "", $options = "", $required = false, $customtype = false)
    {
        $html = '';
        $html .= $customtype == 'checkbox' ? "<div class='checkbox-group ".($required ? " required" : "")."'>" : '';
        $html .= $customtype == 'select_menu' ? "<select name='participant_question[]' class='form-control' " . ($required ? " required" : "")
            . ">" : '';

        if (empty($options)) {
            switch ($customtype) {
                case "text":

                    $html .= " 
                <input type='text' name='participant_question[]' class='form-control'" . ($required ? " required" : "")
                        . ">";
                    break;

                case "file":
                    $html .= " 
                <input type='file' name='participant_question[]' class='form-control'" . ($required ? " required" : "") . ">";
                    break;

                case "long_text":
                    $html .= "
            <textarea name='participant_question' class='form-control' rows='3'" . ($required ? " required" : "") . ">"
                        . $name .
                        "</textarea>";
                    break;
            }
        } else {
            foreach ($options as $option) {
                switch ($customtype) {
                    case "checkbox":
                        $html .= " 
        <div class='form-check'>
            <input type='checkbox' name='participant_question[]' value='" . $option->value . "' class='form-check-input' >
                <label class='form-check-label' for='exampleCheck1'>" . $option->value . "</label>
        </div>";
                        break;
                    case "radio_btn":
                        $html .= " 
            <div class='form-check'>
                <input type='radio' name='participant_question[]' value='" . $option->value . "' class='form-check-input'" . ($required ? " required" : "") . ">" .
                            '    <label class="form-check-label" for="exampleCheck1">' . $option->value . '</label>' .
                            "</div>";
                        break;
                    case "select_menu":
                        $html .= "<option value='" . $option->value . "'>" . $option->value . "</option>";
                        break;
                }
            }
        }
        $html .= $customtype == 'select_menu' ? "</select>" : '';
        $html .= $customtype == 'checkbox' ? "</div>" : '';

        return $html;
    }
}

Then in the view the getHtmlInput() is used like:

@foreach($selectedRtype['questions'] as $customQuestion)
  <div class="form-group">
      <label for="participant_question">{{$customQuestion->question}}</label>
      @if($customQuestion->hasOptions() && in_array($customQuestion->type, ['checkbox', 'radio_btn', 'select_menu']))
          {!! $customQuestion->getHtmlInput(
              $customQuestion->name,
              $customQuestion->options,
              ($customQuestion->pivot->required == '1'),
              $customQuestion->type)
          !!}

      @else
          {!! $customQuestion->getHtmlInput(
              $customQuestion->name,
              [],
              ($customQuestion->pivot->required == '1'),
              $customQuestion->type)
          !!}
      @endif
      <input type="hidden"
             name="participant_question_required[]"
             value="{{ $customQuestion->pivot->required }}">
      <input type="hidden"
             value="{{ $customQuestion->id }}"
             name="participant_question_id[]"/>
  </div>
@endforeach
like image 986
johnW Avatar asked Jun 13 '18 11:06

johnW


People also ask

What is the method of collecting data by preparing a list of questions to respondents to answer?

QUESTIONNAIRES. This is the process of collecting data through an instrument consisting of a series of questions and prompts to receive a response from individuals it is administered to. Questionnaires are designed to collect data from a group.

How does your chosen data collection strategy help you achieve your research purpose?

Data collection is a systematic process of gathering observations or measurements. Whether you are performing research for business, governmental or academic purposes, data collection allows you to gain first-hand knowledge and original insights into your research problem.


1 Answers

I've slightly modified the HTML file structure.

<form method="post" id="registration_form" action="http://proj.test/conference/1/conference-title/registration/storeRegistration">

{{csrf_field()}}

<h6>Participant - 1 - general</h6>
<div class="form-group">
    <label for="namegeneral_1">Name</label>
    <input type="text" id="namegeneral_1" name="participant[1][name]" required="" class="form-control" value="">
</div>

<div class="form-group">
    <label for="surnamegeneral_1">Surname</label>
    <input type="text" id="surnamegeneral_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 - general</h6>

<div class="form-group">
    <label for="namegeneral_2">Name</label>
    <input type="text" id="namegeneral_2" name="participant[2][name]" required="" class="form-control" value="">
</div>

<div class="form-group">
    <label for="surnamegeneral_2">Surname</label>
    <input type="text" id="surnamegeneral_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 - 1 - plus</h6>

<div class="form-group font-size-sm">
    <label for="nameplus_1">Name</label>
    <input type="text" id="nameplus_1" name="participant[3][name]" required="" class="form-control" value="">
</div>

<div class="form-group font-size-sm">
    <label for="surnameplus_1">Surname</label>
    <input type="text" id="surnameplus_1" 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">

I will store all the ‍participants in an array named participant and send thme to Backend

output :

array:2 [▼
  "_token" => "WDtDV0CL6OKVCsGSi5HNyi4HQ6Pmo6VAwzDsgYK1"
  "participant" => array:3 [▼
    1 => array:5 [▼
      "name" => "ali"
      "surname" => "shahabi"
      "answer" => "0937"
      "question_id" => "1"
      "rtypes" => "1"
    ]
    2 => array:5 [▼
      "name" => "danyal"
      "surname" => "shahabi"
      "answer" => "0938"
      "question_id" => "1"
      "rtypes" => "1"
    ]
    3 => array:3 [▼
      "name" => "baba"
      "surname" => "babaei"
      "rtypes" => "2"
    ]
  ]
]

storeRegistration method .

I removed validation from the code and focused on the logic of the program:

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

    # all_participants field
    $allParticipants = Conference::where('id', $id)->first()->all_participants;

    $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 = ($allParticipants) ? $participant['name'] : '';
        $surname = ($allParticipants) ? $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');
}
like image 117
Alihossein shahabi Avatar answered Sep 20 '22 09:09

Alihossein shahabi