How to compare array values to check correct answer - php

I am working on a quiz app, so the users have MCQ's and on submitting the quiz I need to show the result.
Here is the answers table in the mysql db. Similarly, There is questions table which has the id and question columns, containing the question id and question respectively.
So I am querying the db from the model like this, this returns me an associative array:
$testQuery = $this->db->query("SELECT quiz_id, correct_option FROM answers");
if ($testQuery->num_rows() > 0) {
return $testQuery->result_array();
}
Here, I'm printing the array in my controller, Which looks like this on doing the foreach:
$allCorrectOptions = $this->DataModel->readCorrectOptions();
$asize = sizeof($allCorrectOptions);
for($i = 0; $i < $asize; $i++){
echo "<pre>";
var_dump($allCorrectOptions[$i]);
echo "</pre>";
}
The Result of the above snippet:
array(2) {
["quiz_id"]=>
string(2) "13"
["correct_option"]=>
string(13) "Maruti suzuki"
}
array(2) {
["quiz_id"]=>
string(2) "14"
["correct_option"]=>
string(6) "Kotlin"
}
array(2) {
["quiz_id"]=>
string(2) "15"
["correct_option"]=>
string(4) "BOSS"
}
In the view there are radio input tags and the name attribute contains an array (allques) with quiz_id as key so when the user submits the test, I'm doing this to get the quiz_ids and selected values.
$nums = $this->input->post('allques');
foreach ($nums as $key => $value) {
echo "<br>" . $key . "==" . $value;
}
The Result of the above snippet:
13==Maruti suzuki
14==MongoDB
15==Ubuntu Linux
So what I am thinking of doing is, getting the array result of the db query similar to the the snippet result above, so that I can compare the quiz_id and correct_option's with the user submitted values with the help of a loop like: if quiz_id.this == submitted quiz_id && correct_option.this == submitted value then correct_answers++. After that showing the result
If this approach of checking is not effective, then is there any other way to do this properly.

I have figured it out, it can be done like this.
foreach ($allCorrectOptions as $key) {
echo $key['quiz_id'] . "==" . $key['correct_option'] . "<br>";
}

Related

Check if array contains a duplicate value in string with PHP

I want to check if my array contains a duplicate value. I have a form where i pass a Chapter ID with the following method:
<input name="chapter_id[]" type="number" value="<?= $row_chapter_list['chapter_id'] ?>">
To update my database i pick this input and do the update w/o any issues:
if (isset($_POST['chapter_id'])) {
// Update Kapitelnummer
$statement = $pdo->prepare("UPDATE questionaire_chapter SET chapter_id = :chapter_id WHERE id = :id");
$statement->bindParam(":chapter_id", $chapter_id, PDO::PARAM_STR);
$statement->bindParam(":id", $id, PDO::PARAM_INT);
foreach ($_POST['chapter_id'] as $index => $chapter_id) {
$id = $_POST['chapter_inc_id'][$index];
$statement->execute();
}
}
A typical var_dump result looks like:
array(3) { [0]=> string(1) "1" [1]=> string(2) "12" [2]=> string(2) "12" }
In this array example the value "12" is present in two strings. I would like to create a mechanic to count double values and and use the result in a PHP if/else. i want to avoid that the a duplicate chapter ID gets written into my database.
My first try to count the string is this:
print_r(array_count_values($_POST['chapter_id']));
Which gives me a result like this
Array ( [1] => 1 [12] => 2 )
Now i am missing the method to implement a if else to check if the result is not 1.
Any idea how to do this?
You can use array_unique() to get an array where any duplicates has been filtered out. Using that, you can compare it to the original array:
if ($array != array_unique($array)) {
echo "The arrays are not the same, which means that there are duplicates";
}

PHP loop through array and if key1 add operator to variable

I have not coded in many years and have decided to make my own golf statistics program.
I have an issue with going through an array and getting the data I want out. I'm guessing it is very simple but I'm very rusty and tried to read myself to this. Thankful for any help.
For the below code I want $dismade to be 8 it now returns 4?
<?php
$score = array(
"4" => "4",
"3" => "4",
"4" => "4"
);
$dismade = 0;
foreach ($score as $stroke => $dis) {
if($stroke == 4) {
$dismade = $dis + $dismade;
}
}
echo $dismade;
?>
UPDATE!!
That worked well. Thanks. Now i have another issue where i would need to do this 18 times. I tried doing like below without luck. What i want to do is to check the foreach array 1-18. They will all be the same with 9 keys inside. Am i thinking correctly on this? The below only gets the first position. $row[fp1] for example will always be key 2 but can have alot of values inside which i want to go through and add to $gir and then move on to fp2 and so on to 18 and add into $gir array. I hope my question makes sense.
$hole1 = array();
$hole2 = array();
$result = mysql_query($sql) or die ("Couldn't select table at!!");
while ($row = mysql_fetch_array($result)) {
$hole1[$row[rid]] = array($row[s1],$row[p1],$row[gir1],$row[ngir1],$row[fp1],$row[fw1],$row[ud1],$row[ss1],$row[pen1]);
$hole2[$row[rid]] = array($row[s2],$row[p2],$row[gir2],$row[ngir2],$row[fp2],$row[fw2],$row[ud2],$row[ss2],$row[pen2]);
}
mysql_free_result($result);
$gir = array();
foreach (array_combine($hole1,$hole2) as $value) {
if($value[2] == 1) {
array_push($gir,$value[4] );
}
}
print_r ($gir);
There is a problem with your $score keys. As you can see you have a duplicate key "4".
Try something like:
$score = array([4,4], [3,4], [4,4]);
$dismade = 0;
foreach ($score as $value) {
if($value[0] == 4) {
$dismade += $value[1];
}
}
echo $dismade;
Have a nice day.
Because you have an duplicate key "4" in your array, since every key is unique in
array so the third line "4" => "4" will overlap the first line within array.

How can I extract data in an ordered way from a php array?

I'm not a php ninja, so please bear with me on my query. I have the following code (in simplified example format here as a lot of other irrelevant stuff is happening in the real code):
Database connection already successfully defined and handled by an include at the start of the php file.
// Define our $now value to compare times with
$now = time();
// Define the numerical timestamps required for calculating stuff
$min1st = 5140800; //59.5 days
$max1st = 5227200; //60.5 days
$min2nd = 7732800; //89.5 days
$max2nd = 7819200; //90.5 days
$delmar = 10368000; //120 days
// Get each relevant entry from the key table
try {
$stmt = $conn->prepare("SELECT * FROM keyTable WHERE `status` = 'neutral' ORDER BY `lastModified` ASC");
$stmt->execute();
$result = $stmt->fetchAll();
} catch(PDOException $e) { catchMySQLerror($e->getMessage()); }
// Set up some instance counters
$a = 0;
$b = 0;
$c = 0;
// Create some arrays to pop the data into from the next stage so we can use it again later
$arrA = array();
$arrB = array();
$arrC = array();
So far so good. The next part is designed to discover which of the database results have a "lastModified" value set within a specified timeframe, using some data we set up near the top. This works too, fairly well (I think).
foreach($result as $value) {
// Lets find the ones that qualify for first email notification
if((($value['lastModified'] + $min1st) < $now) && (($value['lastModified'] + $max1st) > $now)) {
// Now only the entries that have been untouched for 60 days from today are listed here. Yay! Send out an email to the people responsible and remind them! Get user data...
try {
$stmt = $conn->prepare("SELECT * FROM users WHERE `uID` = :uid");
$stmt->bindValue(':uid', $value['uID']);
$stmt->execute();
$uRes = $stmt->fetchAll();
} catch(PDOException $e) { catchMySQLerror($e->getMessage()); }
// Add +1 to the incremental count
$a++;
// Collect some data for the log email
$arrA[] = $value['entryKey']."-"$value['entryID'];
$arrA[] = $value['entryName'];
$arrA[] = $value['entryTitle'];
$arrA[] = $value['dateStarted'];
$arrA[] = $value['lastModified'];
$arrA[] = $uRes[0]['title']." ".$uRes[0]['firstName']." ".$uRes[0]['lastName'];
$arrA[] = $uRes[0]['email'];
Then it will on to send each person that gets turned up in this if. The code for sending the emails out etc works perfectly, so no need to bore you all with that. The same process is repeated each time with other parameters - you can likely guess how that works by observing the other numerical timestamp values near the top. So lets go to the end of this (which is where the question lies, after the:
}
}
And now here I want to pull all the data out of $arrA (and also the respective other arrays $arrB and $arrC) so I can pop that all into a tidy table then mail it off to admin so they know what exactly happened when this was all run.
My issue is, I do not know how to extract in a usable way, $arrA. If I var_dump($arrA); I successfully get all the stuff that should be in there but I don't see a way to order it in a nice row by row method per loop performed. I tend to end up with this when performing a var_dump($arrA);:
array(14) { [0]=> string(15) "ABC-63" [1]=> string(36) "Fish and Chips" [2]=> string(33) "Cod Disposal" [3]=> string(22) "1447283057" [4]=> string(22) "1447286317" [5]=> string(21) "Mr Bob Smith" [6]=> string(22) "bob.smith#mail.com" [7]=> string(15) "XYZ-104" [8]=> string(23) "Blue Socks" [9]=> NULL [10]=> string(22) "1447286691" [11]=> string(22) "1447326523" [12]=> string(20) "Mrs Rosie Jones" [13]=> string(34) "r.jones#mail.com" }
Clearly there is output here for two data entries. I'd to know how to shape this into an output that would basically look like this:
<tr>
<td>ABC-63</td>
<td>Fish and Chips</td>
<td>Cod Disposal</td>
<td>1447283057</td>
<td>1447286317</td>
<td>Mr Bob Smith</td>
<td>bob.smith#mail.com</td>
</tr>
<tr>
<td>XYZ-104</td>
<td>Blue Socks</td>
<td>NULL</td>
<td>1447286691</td>
<td>1447326523</td>
<td>Mrs Rosie Jones</td>
<td>r.jones#mail.com</td>
</tr>
Table start and end would obviously be in place before and after the loop respectively.
How can I achieve this result from $arrA? Do I need to modify the way I am storing this data in array's earlier on, in some manner, in order to have some sort of easy way to manage this output near the end?
Thanks in advance.
If I understand correctly, you want to output elements of $arrA, 7 elements per line.
What you can do is iterate over $arrA, filling up a temporary array $line with the elements of $arrA. Every 7 elements, the line will be filled up. You can then do anything with it like echoing it to standard output our adding it to an email variable, and then reset the $line.
$line = [];
for ($i = 0; $i < count($arrA); $i++) {
$line[] = $arrA[$i];
if ($i % 7 == 6) { //line is filled up with 7 elements
echo implode($line, " | "); //output elements of line separated with pipe char
$email .= implode($line, " | ") . "\n"; //add the line to email body
$line = []; //reset line
}
}
This one's gonna help:
foreach($arrA as $index=>$value){
echo($value.' |');
}
Styling is up to you. But if you need further help, keep me updated.
Thanks to #quentinadam I was inspired to try this. It's not the angle I was thinking of using but it does work.
echo "<table border=\"1\">\n<tbody><tr>\n";
$i = 0;
foreach($arrA as $thing) {
if($i == 7) {
echo "</tr>\n<tr>\n";
}
echo "<td>".$thing."</td>\n";
$i++;
if($i == 8) {
$i = 1;
} else {
$i = $i;
}
}
echo "</tr></tbody>\n</table>\n\n";
I'd up-vote quentinadam for being on the right track but cannot yet up-vote.

How to insert database rows if there are no answers

I am trying to insert each answer for each question in the database. Problem is that there is a possibility that a question may have no answers, so I tried the code below but it does not insert a db row if a question has no answer, what I was trying to do is that if no answer then display the string No Answer under the Answer column for that question:
$answersql = "INSERT INTO Answer (QuestionId, Answer)
VALUES (?, ?)";
if (!$insertanswer = $mysqli->prepare($answersql)) {
// Handle errors with prepare operation here
echo __LINE__.': '.$mysqli->error;
}
if( $insert && $insertanswer)
{
$c = count($_POST['numQuestion']);
$question_ids = array();
for($i = 0; $i < $c; $i++ )
{
... //Question INSERT goes here
$questionId = $mysqli->insert_id;
$question_ids[$questionNo] = $questionId;
}
$results = $_POST['value'];
foreach($results as $id => $value)
{
$answer = $value;
$quesid = (int)$question_ids[$id];
foreach($value as $answer)
{
if($answer == '' || $answer === null){
$answer = 'No Answer';
}
$insertanswer->bind_param("is", $quesid, $answer);
$insertanswer->execute();
if ($insertanswer->errno) {
// Handle query error here
echo __LINE__.': '.$insertanswer->error;
break 7;
}
}
}
//close your statements at the end
$insertanswer->close();
}
The ['value'] comes from an input:
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');
Below is the SHOW CREATE TABLE for the Answer Table:
CREATE TABLE `Answer` (
`AnswerId` int(10) NOT NULL AUTO_INCREMENT,
`QuestionId` int(10) NOT NULL,
`Answer` varchar(10) DEFAULT NULL,
PRIMARY KEY (`AnswerId`)
) ENGINE=InnoDB AUTO_INCREMENT=280 DEFAULT CHARSET=utf8
Below is a var dump where if I set question 1 to have answers B and C, question 2 to have no answers, question 3 to have answer B and question 4 to have no answer, it outputs the following from var dump:
var_dump($question_ids);
var_dump($results);
array(4) {
[1]=> int(265)
[2]=> int(266)
[3]=> int(267)
[4]=> int(268)
}
[1]=> array(2) {
[0]=> string(1) "B"
[1]=> string(1) "C"
}
[3]=> array(1) {
[0]=> string(1) "B"
}
So it outputs those set of answers in questions 1 and 3. But does not post No Answer for question 2 and 4.
If all questions had an answer as thisL
question 1: B C
question 2: A
question 3: B
question 4: A C
Then the var dump displays this in var dump:
array(4) {
[1]=> int(277)
[2]=> int(278)
[3]=> int(279)
[4]=> int(280)
}
array(4) {
[1]=> array(2) {
[0]=> string(1) "B"
[1]=> string(1) "C" }
[2]=> array(1) {
[0]=> string(1) "A"
}
[3]=> array(1)
{
[0]=> string(1) "B"
}
[4]=> array(2)
{
[0]=> string(1) "A"
[1]=> string(1) "C"
} }}
As you can see for each question is inserts the relevant answers. So the issu is if the question has no answers that it does not insert a db row and state No Answer. My question is how to include a No Answerfor each question in the db that has no answers selected in those questions?
Simply do not insert anything into Answer table when there is no answer. Rest of your solution is basically correct.
When displaying questions with answer, check if there is answer (empty select result or null in left joined column) to show and if not, show "No answer". But there is no "No answer" in database.
When your code get to $results = $_POST['value'];, $question_ids is populated with the ids of questions that must be included in the table.
My suggestion is to remove elements from this array right after including the first answer to the related question. This way, after the foreach($results as $id => $value) loop, this array will contain only questions without explicit answers. The next step is just to include these pseudo-answer "No answer" in the DB.
The relevant code for you (inserted lines are //* commented):
$notAnswered = $question_ids; //* Make a copy
$results = $_POST['value'];
foreach ($results as $id => $value) {
$answer = $value;
$quesid = (int)$question_ids[$id];
$pos = array_search($quesid, $notAnswered); //* Search for it
if ($pos !== false) //* It's in the array
array_splice($notAnswered, $pos, 1); //* Delete it from the array
foreach ($value as $answer) {
$insertanswer->bind_param("is", $quesid, $answer);
$insertanswer->execute();
if ($insertanswer->errno) {
// Handle query error here
echo __LINE__.': '.$insertanswer->error;
break 7;
}
}
}
//* Insert 'No Answer' for each question not answered
foreach ($notAnswered as $id) {
$insertanswer->bind_param('is', $id, 'No Answer');
$insertanswer->execute();
if ($insertanswer->errno) {
// Handle query error here
echo __LINE__.': '.$insertanswer->error;
break 7;
}
}
// Close your statements at the end
$insertanswer->close();
One important thing to note here: array_splice is very slow in PHP for big arrays (>100 elements). But I don't think this is the case here.

Retrieve database information and check results for certain conditions

I am looking for the most efficient method to do the following...
I have a table with three fields: id, eventid and movetype - and I have the following code to query the database for all entries with a matching eventid :
$get_results = mysql_query("SELECT * FROM table WHERE eventid='$eventid'");
while($row = mysql_fetch_array($get_results)){
// store results in array
$move_type_array = explode(" ", $row['movetype']);
}
Please note: movetype can only be three values: Internal, Outgoing, Incoming
Using a set of dummy data, var_dump($move_type_array) could output:
array(1) { [0]=> string(8) "Internal" } array(1) { [0]=> string(8) "Internal" }
Another example of an output would be:
array(1) { [0]=> string(8) "Internal" } array(1) { [0]=> string(8) "Incoming" } array(1) { [0]=> string(8) "Outgoing" }
I then need to check the output to see if the following conditions are met:
Does the array contain Internal twice?
If the array only contains Internal once, then does the array also contain Incoming and Outgoing?
If either of the conditions are met then a message should be displayed telling them which condition has been met, otherwise a message should tell them that the conditions have not been met.
I have tried using a number of PHP functions such as in_array(), and also tried storing the data in a string and using preg_match() however I was unsuccessful in both methods.
Try this:
$result = mysql_query("
SELECT SUM(IF(movetype = 'Internal', 1, 0)) AS internal,
SUM(IF(movetype = 'Outgoing', 1, 0)) AS outgoing,
SUM(IF(movetype = 'Incoming', 1, 0)) AS incoming
FROM table
WHERE eventid = $eventid
GROUP BY eventid
");
$count = mysql_fetch_array($result);
if ($count['internal'] >= 2 || ($count['internal'] == 1
&& $count['outgoing'] >= 1
&& $count['incoming'] >= 1)) {
echo 'Yes';
} else {
echo 'No';
}
// 1. Don't use '*' - fetch only required fields!
// 2. Don't use mysql_* functions - they are obsolete! Use PDO or MySQLi instead.
$get_results = mysql_query("SELECT `movetype` FROM table WHERE eventid='$eventid'");
while($row = mysql_fetch_array($get_results)){
// Count the values
$arr = array_count_values(explode(" ", $row['movetype']));
// Check them here
if(isset($arr['Internal'])) {
if($arr['Internal'] === 2)
echo ' Internal: 2'.PHP_EOL;
else if($arr['Internal'] === 1
&& isset($arr['Incoming'])
&& isset($arr['Outgoing']))
echo ' Internal: 1, Incoming and Outgoing'.PHP_EOL;
}
}

Categories