-1

I have an application you can view here: APPLICATION

Please follow steps below in order to use the application correctly:

  1. Click on the Add Question button twice to append 2 table rows in the table underneath.

  2. Both table row will have their own file input. In both file inputs upload a video file (I advised a very small video for quickness of upload). You will have to upload video file one at a time

  3. You will see that every time a file is uploaded, underneath the table it will display a text input, the values in the text input is the video id from the database associated for each video file uploaded.

So for example if my Video table currently looks like this:

Video Table:

VideoId (auto PK)  VideoFiles
4                  Files/video1.mp4

If I upload 2 video files (video5.mp4 and video6.mp4) and the text inputs state 5 and 6 respectively, then it means the Video table now looks like thi afterthe upload of files:

Video Table:

VideoId (auto PK)  VideoFiles
4                  Files/video1.mp4
5                  Files/video5.mp4
6                  Files/video6.mp4

Now code for displaying the text inputs is below:

Jquery when upload finishes and generates text input:

function stopVideoUpload(success, videoID, videofilename){

      var result = '';

      if (success == 1){
         result = '<span class="videomsg'+videocounter+'">The file was uploaded successfully</span>';
            $('.hiddenvid').append('<input type="text" name="vidid[]" id="'+videoID+'" value="' + videoID + '" />');
          }

      $(sourceVideoForm).find('.videof1_upload_process').hide();
      $(sourceVideoForm).find('.videomsg').html(result);
      $(sourceVideoForm).find('.videof1_upload_form').show();   


      return true;   
}

Div tag where it stores text inputs:

<div class="hiddenvid"><!-- All uploaded video file ids go here --></div>

Now the issue is below, I want to store in the database which question contains which videos. To do this I will store the question numbers in the Question Table, giving it a QuestionId and want to retrieve the VideoId of the video from the Video Table. So below is what the database tables should look like when submitting and inserting your video files into the db:

Question Table:

QuestionId (auto PK) QuestionNo
25                    1
26                    2

Video_Question Table:

VideoQuestionId (PK auto)  VideoId  QuestionId
7                          5         25
8                          6         26

The issue I am having is I am struggling to INSERT the data for the Video_Question table. The inserting into the Question Table is fine but what I am trying to do is retrieve the last QuestionId submitted and for each QuestionId, retrieve any VideoId which belongs to that QuestionId and insert it into the Video_Question Table?

Below is my attempt but nothing is inserted into the Video Question table, it is giving me an:

Notice: Undefined offset: 0 in .... on line 305 error

How can I fix the error and get the INSERT for the Video_Question to work?

Below is the code for the insert (I have commented the line number where the notce appears):

// Prepare your statements ahead of time
 $questionsql = "INSERT INTO Question (QuestionNo) 
    VALUES (?)";
if (!$insert = $mysqli->prepare($questionsql)) {
    // Handle errors with prepare operation here
    echo __LINE__.': '.$mysqli->error;
}

     $videoquestionsql = "INSERT INTO Video_Question (VideoId, QuestionId)  
        VALUES (?, ?)"; 

         if (!$insertvideoquestion = $mysqli->prepare($videoquestionsql)) { 
          // Handle errors with prepare operation here 
           echo __LINE__.': '.$mysqli->error; 
        } 

    $c = count($_POST['numQuestion']);
    $question_ids = array();

    for($i = 0;  $i < $c; $i++ )
    {

$questionNo = $_POST['numQuestion'][$i];

            $insert->bind_param("i", $questionNo);

            $insert->execute();

            if ($insert->errno) 
            {
                // Handle query error here
                echo __LINE__.': '.$insert->error;
                break 3;
            }

            $questionId = $mysqli->insert_id;

            $question_ids[$questionNo] = $questionId;


}

                $vidresults = $_POST['vidid'];
            foreach($vidresults as $vidid => $vidvalue) 
            {

                $video = $vidvalue;

                $vidquesid = $question_ids[$vidid];  

                foreach($vidvalue as $video) 
                {

    $insertvideoquestion->bind_param("ii",$video, $vidquesid); 

        $insertvideoquestion->execute(); 

                    if ($insertvideoquestion->errno) { 
              // Handle query error here 
              echo __LINE__.': '.$insertvideoquestion->error;
              break 4;
            } 

        }
    }

By doing the following var_dumps:

var_dump($question_ids);
var_dump($vidid);

I get these results:

array(2) { 
[1]=> int(159)
[2]=> int(160) 
} int(1)

UPDATE:

What I don't understand is that the code below which is very similar works, but how come this works and the mysqli code I have for video doesn't work:

$results = $_POST['value'];
foreach($results as $id => $value) 
{
    $answer = $value;

    $quesid = $question_ids[$id];   

    foreach($value as $answer) 
    {
        $insertanswer->bind_param("is", $quesid, $answer);

        $insertanswer->execute();

        if ($insertanswer->errno) {
            // Handle query error here
            echo __LINE__.': '.$insertanswer->error;
            break 5;
        }
    }
}

Jquery:

   var $this, i = 0,
       $row, $cell;
   $('#optionAndAnswer .answers').each(function () {
       $this = $(this);
       if (i % 6 == 0) {
           $row = $("<tr/>").appendTo($answer);
           $cell = $("<td/>").appendTo($row);
       }
       var $newBtn = $(("<input class='answerBtnsRow answers' type='button' style='display:%s;' onclick='btnclick(this, " + gQuestionIndex + ");' />")
                       .replace('%s', $this.is(':visible') ? 'inline-block' : 'none')).attr('name', "value[" + gQuestionIndex + "][]")
           .attr('value', $this.val()).attr('class', $this.attr('class')).attr('id', $this.attr('id') + 'Row');
       $newBtn.appendTo($cell);

       i++;
   });
user1881090
  • 739
  • 4
  • 16
  • 34

1 Answers1

1

$question_ids is a one indexed array. You didn't post the code that initializes that array, so I'm not why it's a one indexed array, but whatever. On the other hand, $vidresults comes from a POST array, which is zero indexed unless you specify keys (you aren't). You then iterate through $vidresults, assigning the keys (starting from zero) to $vidid and then try to access $question_ids using those keys on this line:

$vidquesid = $question_ids[$vidid];

But, as the notice says, the first key from $vidresults, zero, does not exist in $question_ids. If for some reason $question_ids has to be one-indexed, you can change the iteration, add one to the key, or change the html to specify the index (that could be problematic because of how you generate the input elements).

I don't know if there are any official sources for this kind of thing. This question describes HTTP array syntax.

Edit: You posted this:

$questionNo = $_POST['numQuestion'][$i];

But you didn't post the related html/jquery. The html looks likes this:

<th colspan="2">
    Question Number <span class="questionNum">1</span>
    <input type="hidden" class="num_questions" name="numQuestion" value="1">
</th>

And the jquery (doesn't matter, just to show that it isn't changing the input type to an array):

function insertQuestion(form) {   
  if (qnum > 5) {
    return;
  }
  var $tbody = $('#qandatbl_onthefly > tbody');
  var $tr = $("<tr class='optionAndAnswer' align='center'>");
  var $qid = $("<td width='5%' class='qid'></td>").text(qnum);
  var $video = $("<td width='17%' class='video'></td>");
  var $questionType = '';

  $('.num_questions').each( function() {
  var $this = $(this);
  var $questionNumber = $("<input type='hidden'
    class='num_questionsRow'>").attr('name',$this.attr('name')+"[]")
      .attr('value',$this.val());
  $qid.append($questionNumber);                              
  ++qnum;
  $(".questionNum").text(qnum);
  $(".num_questions").val(qnum);
  --qremain;
  $(".questionRemain").text(qremain);
});

So, I was wrong the first time, though the issue I pointed out likely still needs to be fixed. The problem though is that you are manually iterating from 0 to count($_POST['numQuestions']). But $_POST['numQuestions'] is an integer, not an array, and as this page points out in the Return Values section, count will return 1 for a value which is not an array. Thus, you are trying, on the first iteration, to access $_POST['numQuestions'][0], triggering the notice that index zero does not exist.

Note: I saw the comment referencing some earlier issues with bounty protocol. I'm hoping that doesn't apply here.

Edit 2: The code that you added uses a foreach loop, which will never attempt to access an unset index. That being said, you were still trying to iterate with a for loop over an integer, and no looping construct will fix that. That is to say, there is something wrong with your approach, and you'll have to reconsider your intentions to decide how to resolve it. I think I've answered the question, but I'd be happy to respond to a new question, posted separately, if you want to rephrase the design issue.

Community
  • 1
  • 1
Tim
  • 1,011
  • 6
  • 12
  • I included the necessary code in question so you know where the `$questionids` are coming from – user1881090 Jan 26 '13 at 11:27
  • What I don't understand is that I have similar code which I included in update and that works fine, that code goes underneath the mysqli video code I have, why does that work with no problems? What code do I need to include to fix this? – user1881090 Jan 26 '13 at 22:35
  • ok, that is fair, I will link you to the seperate question. Hopefully you can answer the seperate question as you have got understanding on this – user1881090 Jan 27 '13 at 05:31
  • link to seperate question: http://stackoverflow.com/questions/14544750/design-of-code-needs-changing-in-order-for-insert-to-work – user1881090 Jan 27 '13 at 05:36