Good day # all.
I've this code snippet which's aim is to display the Exam this user is qualified to take based on the courses registered for. It would display the Exam Name, Date Available, Passing Grade and either Take Exam link if he/she hasn't written or View Result if he/she has written previously.
/*Connection String */
global $con;
$user_id = $_SESSION['user_id']; //user id
$courses = parse_course($user_id); //parse course gets the list of registered courses (Course Codes) in an array
foreach ($courses as $list)
{
$written = false;
$list = parse_course_id($list); //parse_course_id gets the id for each course
$ers = mysqli_query($con, "Select * from exams where course_id = '$list'");
while ($erows = mysqli_fetch_assoc($ers)) {
$trs = mysqli_query($con, "Select * from result_data where user_id = '$user_id'");
while ($trows = mysqli_fetch_assoc($trs)) {
if ($trows['user_id'] == $user_id && $trows['exam_id'] == $erows['exam_id'])
$written = true;
else
$written = false;
}
if($written)
{
echo "<tr><td>".$erows['exam_name']."</td><td>".$erows['exam_from']." To ".$erows['exam_to']."</td><td>".$erows['passing_grade']."%</td><td>".'View Result '."</td></tr>";
$written = false;
}
else
{
echo "<tr><td>".$erows['exam_name']."</td><td>".$erows['exam_from']." To ".$erows['exam_to']."</td><td>".$erows['passing_grade']."%</td><td>".'Take Exam '."</td></tr>";
$written = false;
}
}
}
But It only displays one View Result entry even if I've taken more than one exam. It shows the recent entry. Please what am I missing?
Untested, but here's how I would do it.
I've assumed $user_id is an integer. I'm a bit worried about it being used in SQL without any sanitization. I can't guarantee anything else you're doing is secure either because I can't see your other code. Please read: http://php.net/manual/en/security.database.sql-injection.php
(Oh I see someone already commented on that - don't take it lightly!)
Anyway, my approach would be to collect the user's written exam IDs into an array first. Then loop through the available exams and check each exam id to see if it's in the array we made earlier.
I wouldn't bother looking into the join advice unless you find this is performing poorly. In many systems it would be common to have 3 functions in this situation, one that generates $users_written_exam_ids ones that pulls up something like $all_available_exams and then this code which compares the two. But because people are seeing both queries here together there is a strong temptation to optimize it, which is cool but you probably just want it to work :)
<?php
global $con;
// Get the user id. Pass through intval() so no SQL injection is possible.
$user_id = intval($_SESSION['user_id']);
// Parse course gets the list of registered courses (Course Codes) in an array
$courses = parse_course($user_id);
foreach ($courses as $list)
{
// Gets the id for each course
$list = parse_course_id($list);
$users_written_exam_ids = array();
$trs = mysqli_query($con, "SELECT exam_id FROM result_data WHERE user_id = '$user_id'");
while ($trows = mysqli_fetch_assoc($trs))
{
$users_written_exam_ids[] = $trows['exam_id'];
}
$ers = mysqli_query($con, "SELECT * FROM exams WHERE course_id = '$list'");
while ($erows = mysqli_fetch_assoc($ers)) {
echo '<tr><td>' . $erows['exam_name'] . '</td><td>' . $erows['exam_from']
. ' To ' . $erows['exam_to'] . '</td><td>' . $erows['passing_grade']
. '%</td><td>';
if (in_array($erows['exam_id'], $users_written_exam_ids))
{
echo 'View Result';
}
else
{
echo 'Take Exam';
}
echo '</td></tr>';
}
}
Related
I'm new to PHP as well as the field and have been tasked with finding inconsistencies amongst tables from different mySQL databases. Every table should be the same between databases (column names, column count), with the exception of the actual data held in it, which they are not. I will need to identify the offending columns, the table they are in and, the database they are in. Below is my code thus far:
<?php
chdir(<path>);
include(<file>);
include(<file>);
$db = new db($hostname, $user, $pass, $commondatabase);
// Get baseline DB columns
//$db->select_db('<baseDB>');
//$btq = "SHOW TABLES";
//$btr = $db->query($btq);
//while($trows = $db->fetch_assoc($btr) {
// $bcq = "SHOW COLUMNS FROM ".$btr[<key>];
// $bcr = "$db->query($bcq);
// $basecolumns[] = $bcr;
//}
$dbq = "SELECT * FROM <commonDB>.<DBnames> ORDER BY <DBnamesID>";
$dbr = $db->query($dbq);
while($dbrow = $db->fetch_assoc($dbr)) {
echo "\n";
print_r($dbrow['dbname']);
echo "\n";
$db->select_db($dbrow['dbname']);
$tq = "SHOW TABLES";
$tr = $db->query($tq);
while($table = $db->fetch_assoc($tr)) {
/*print_r($dbtables);*/
$cq = "SHOW COLUMNS FROM ".$table['Tables_in_'.$dbrow['dbname']];
$cr = $db->query($cq);
$dbcols = [];
while($col = $db->fetch_assoc($cr)) {
/*print_r($col);*/ $dbcols = $col;
// Do check against baseline here
//if($dbcols != $basecolumns) {
// $badcolumns[] = $dbcols;
//}
}
}
}
$db->close();
?>
Currently it will loop down to the columns, but the output is not visually pleasing nor very manageable. My first concern is to get this working to where I can loop down to the columns and actually get them in their own arrays to be checked against the baseline and I've hit a wall, so any direction would be much appreciated. Currently each column is being assigned to its own array versus an array of all the column names for the database and table the loop is on. TIA!
Here is what I came up with. Not sure if it's the most DRY way to go about it, but it works and achieves the results I was looking for. Thank you to Barmar for sending me down the right path.
<?php
chdir(<path>);
include(<file>);
include(<file>);
$db = new db($hostname,$user,$pass,$commondatabase);
$db->select_db(<database>);
// Get tables from baseline database
$q="select distinct <column-name> from <table-name> where <where-param> ORDER BY <order-by-param>";
$r=$db->query($q);
while($tables=$db->fetch_assoc($r)) {
$table = $tables[<key>];
$x = array();
$x["$table"]=array();
// Get table columns from baseline database
$q="select <column-name> from <table-name> where <where-param> and <where-param> ORDER BY <order-by-param>";
$r2=$db->query($q);
while ($columns=$db->fetch_assoc($r2)) {
$x["$table"][]=$columns[<key>];
}
// Check other databases for this table
$q="select * from $commondatabase.<table-with-database-names> ";
$q.="where <where-param> order by <order-by-param>";
$r2=$db->query($q);
while ($databases=$db->fetch_assoc($r2)) {
$y = array();
$y["$table"]=array();
// Get table columns in $databases[<key>]
$q="select <column-name> from <table-name> where <where-param> and <where-param> ORDER BY <order-by-param>";
$r3=$db->query($q);
while ($columns=$db->fetch_assoc($r3)) {
$y["$table"][]=$columns[<key>];
}
// Check against baseline
$z1 = array_diff($x["$table"],$y["$table"]);
$z2 = array_diff($y["$table"],$x["$table"]);
// Echo out comparison results
if (empty($z1) && empty($z2)) {
//echo "all good.\n";
} else {
echo "Difference found in {$databases[<key>]}.{$tables[<key>]}:";
if (!empty($z1)) print_r($z1);
if (!empty($z2)) print_r($z2);
}
}
}
$db->close();
?>
First of all, im a beginner so please excuse me if i don't mention things that could be important.
I have Sellers, that are in different countries in the world. Each country belong to a continent. Im trying to:
get the seller name
Fetch Database to see in what countries (China,Italy,Germany...) he offers his goods.
Then fetch another database and see in what continents (ASIA,EU) belong each country
Store the countries (Italy,Germany) to a variable $country_eu and $country_asia (China). So later i will add this variables to update database fields.
if($continent == 'ASIA') is not included in the code YET since i take one by one the steps. I want to make first EU work, then i figure out the rest.
include_once('../db.php');
session_start();
$seller_name = $_SESSION['seller_name'];
echo $seller_name;
if (!empty($_POST['flag_image'])){
$flags_array = $_POST['flag_image'];
$flags_string = implode(",",$flags_array);
}else{
$flags_string = '';
}
$cont_eu = '';
// Assign Flags to Continents
foreach ($flags_array as $flag_image){
$qry_find_flag_continent = " SELECT continent FROM flags WHERE flag_image = '$flag_image' ";
$result = $dbdetails->query($qry_find_flag_continent);
while($row = mysqli_fetch_array($result)) {
$continent = $row["continent"];
if ($continent == 'EU') {
$cont_eu .= $flag_image;
}
}
echo $cont_eu;
The problem with my code is that when i echo $cont_eu is giving me just 1 result(Germany) and not the EXPECTED (Italy,Germany)
Thank you all for your precious time and attempts to help. Here is the new code that works great.
include_once('../db.php');
session_start();
$seller_name = $_SESSION['seller_name'];
echo $seller_name.'<br>';
if (!empty($_POST['flag_image'])){
$flags_array = $_POST['flag_image'];
$flags_string = implode(",",$flags_array);
} else {$flags_string = '';}
// Assign Flags to Continents
foreach ($flags_array as $flag_image){
$qry_find_flag_continent = " SELECT continent FROM flags WHERE flag_image = '$flag_image' ";
$result = $dbdetails->query($qry_find_flag_continent);
while($row = mysqli_fetch_array($result)) {
$continent = $row["continent"];
if($continent == 'EU'){ $eu_flags_array[] = $flag_image;}
}
}
print_r($eu_flags_array); //Gives me Array ( [0] => Germany.png [1] => Italy.png )
I have a basic PHP page which searches a MySQL Database of retro ZX Spectrum magazine articles.
The address is [www.retroresource.co.uk][1]
The PHP Results Page is fine, in that it produced the results, but I would like to be able to group the results by 'fgames.fgname'
So for example if I searched for Dizzy
Dizzy (as a header)
Table with rows that have fgames.fgname = Dizzy
Spindizzy (as a header)
Table with rows that have fgames.fgname = Spindizzy
Treasure Island Dizzy (as a header)
Table with rows that have fgames.fgname = Treasure Island Dizzy
etc etc
I have googled and looked in a few of my text books, but am unable to see a solution. Any help much appreciated.
Peter
Amended Code after assistance (No results though)
<?php
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);
require( '../connect_db.php' ) ;
$query = $_GET['query'];
$min_length = 4;
// you can set minimum length of the query if you want
$query = strip_tags($query);
$query = mysqli_real_escape_string ($dbc,$query);
$q = "SELECT fgames.fgname, fgames.fgprorg, fgames.fgprbud, fgames.fgratng, fgames.fgprdsk, ftypes.fttname, frefs.fryymm, frefs.frpage, frefs.frissue, fmagzne.fmname, frefcde.ffname
FROM fgames, ftypes,frefs, fmagzne,frefcde
WHERE ftypes.fttype = fgames.fgtype
and fgames.fglink = frefs.frlink2
and frefs.frentry = frefcde.ffentry
and frefs.frmag = fmagzne.fmmag
and fgames.fgname LIKE '%".$query."%'
order by fgames.fgname ASC" ;
$r = mysqli_query( $dbc , $q ) ;
$current_group = '';
while ( $row = mysqli_fetch_array( $r , MYSQLI_ASSOC ) )
{
if($row['fgames.fgname']) !== $current_group)
{
if($current_group !== '')
{
echo '</table>';
}
$current_group = $row['fgames.fgname'];
echo '<table><tr><th>FGNAME</th><th>FGPRORG</th><th>FGRBUD</th><th>FGRATNG</th><th>FGRDSK</th>
<th>FTTTNAME</th><th>FRYYMM</th><th>FRPAGE</th><th>FRISSUE</th><th>FMNAME</th><th>FFNAME</th></tr>';
}
echo '<tr><td>'.$row['fgname'].'</td><td>'.$row['fgprorg'].'</td><td> '.$row['fgprbud'].' </td><td>'.$row['fgratng'].' </td> <td>'.$row['fgprdsk'].' </td><td>'.$row['fttname'].'</td><td> '.$row['fryymm'].'</td><td> '.$row['frpage'].'</td><td> '.$row['frissue'].' </td> <td>'.$row['fmname'].' </td><td>'.$row['ffname'].'</td></tr>';
}
echo '</table>';
else
{
echo '<p>' . mysqli_error( $dbc ) . '</p>' ;
}
# Close the connection.
mysqli_close( $dbc ) ;
?>
There are two basic approaches.
Either load the query data into a two dimensional array and output with nested loop like this:
$array_for_output = array();
while($row = /* your query fetch mechanism here */) {
$array_for_output[$row['field_you_are_grouping_on']] = $row;
}
foreach($array_for_output as $table_name => $table_data) {
// output table header here
foreach($table_data as $table_row) {
// output individual row
}
// output table closure here
}
Or the other approach is to query using an ORDER BY clause on the field you are trying to group by and detect changes in the current group in single loop
$query = "
SELECT ...
FROM ...
WHERE ...
ORDER BY field_you_are_grouping_on, any_secondary_ordering_field_here ASC";
// execute query here
$current_group = '';
while ($row = /* your query fetch mechanism here */) {
if($row['field_you_are_grouping_on']) !== $current_group) {
// we have started a new group
if($current_group !== '') {
// this is not first table
// so output closure to previous table here
}
$current_group = $row['field_you_are_grouping_on'];
// output new table header here
}
// output row data here
}
// output closure to final table here
The second approach is usually preferable from a memory management standpoint (you don't have to store entire result set in memory at any point), but some beginning developers may not find this not as intuitive as the first method. The first method also may be more appropriate if you want to take the full result set and inject it into some sort of template that is used to render the display.
I am trying to display a set of offices ordered under a header that reflects the state in which the offices are located, like so:
State
Office
Office
...
State
Office
...
I have beat my head against this one for a while. There is a single table 'offices' in the MySQL db which has each office's State listed under 'office_state'. Here's what I've come up with - but nothing is returned.
// Here I return a list of the distinct States:
$stateQuery = 'SELECT DISTINCT office_state AS state FROM offices';
$stateResult = mysql_query($stateQuery);
// Here I return each office's information:
$officeQuery = 'SELECT office_information, office_state FROM offices';
$officeResult = mysql_query($officeQuery);
// And here's where I'm stuck:
while ($rows = mysql_fetch_assoc($stateResult)) {
// This returns the distinct States:
echo $rows['state'];
// Here is my effort at listing each office within the State:
$rows1 = mysql_fetch_assoc($officeResult);
if ($rows['state'] == $rows1['office_state']) {
echo $rows1['office_information'];
}
}
Any help would be much appreciated.
try this
<?php
// Here I return a list of the distinct States:
$stateQuery = 'SELECT DISTINCT office_state AS state FROM offices';
$stateResult = mysql_query($stateQuery);
// Here I return each office's information:
$officeQuery = 'SELECT office_information, office_state FROM offices';
$officeResult = mysql_query($officeQuery);
// And here's where I'm stuck:
while ($rows = mysql_fetch_array($stateResult)) {
// Here is my effort at listing each office within the State:
while($rows1 = mysql_fetch_array($officeResult)){
if ($rows['state'] == $rows1['office_state']) {
echo $rows1['office_information'];
}
}
}
?>
My question is very simple. The code I have written here produces absolutely no output on the webpage. I've been at it all day and I'm sure that it's something very simple that I am being an idiot for missing. So I am appealing to your good-natured fresh eyes! If anyone can spot a reason why this isn't working, I'd be very grateful.
The premise:
This is a decision tree online survey that has the following conditions: if a user has already started the survey, it will find them in the database, find their last answered question and display the next one. But if they haven't started, it will display the first question.
All survey questions are held in the database as well as the decision tree logic (for instance, if the user chooses option 2 for question 1, they will be directed to question 3, not 2).
Please assume that for the moment, I am updating relevant info directly from the database and not automating it on the website.
Thanks :)
PHP:
<?php
//Find the latest question reached by the user for display on the page
$sql = mysql_query("SELECT QuestionNumberReached FROM User WHERE EmailAddress = '***'");
$sqlCount = mysql_num_rows($sql);
if ($sqlCount > 0) {
while ($row = mysql_fetch_array($sql)) {
$QuestionNumberReached = $row["QuestionNumberReached"];
}
}
?>
<?php
//Find the last question answered by the user from the database
$StartedQuery = mysql_query("SELECT LastQuestionAnswered FROM User WHERE EmailAddress = '***'");
//Count the number of rows that the query produces
$StartedQueryCount = mysql_num_rows($StartedQuery);
//If data is found, whether it be a number or null, define the value
if ($StartedQueryCount > 0) {
while ($row = mysql_fetch_array($sql)) {
$LastQuestionAnswered = $row["LastQuestionAnswered"];
//If the field has a value and is not null, find the next question from the database
if (!empty($LastQuestionAnswered)) {
//Find the User's ID and the ID of the last question answered
$sqlA = mysql_query("SELECT PKID, LastQuestionAnswered FROM User WHERE EmailAddress = '***'");
//If the operation produces an error, output an error message
if (!$sqlA) {
die('Invalid query for SQLA: ' . mysql_error());
}
//Count the number of rows output
$sqlACount = mysql_num_rows($sqlA);
//If rows exist, define the values
if ($sqlACount > 0) {
while ($row = mysql_fetch_array($sqlA)) {
$sqlAPKID = $row["PKID"];
$sqlALastQuestionAnswered = $row["LastQuestionAnswered"];
}
}
//Find the answer given by the user to the last answered question
$sqlB = mysql_query("SELECT Answer FROM Responses WHERE User = $sqlAPKID");
//If the operation produces an error, output an error message
if (!$sqlB) {
die('Invalid query for SQLB: ' . mysql_error());
}
//Count the number of rows output
$sqlBCount = mysql_num_rows($sqlB);
//If rows exist, define the values
if ($sqlBCount > 0) {
while ($row = mysql_fetch_array($sqlB)) {
$sqlBAnswer = $row["Answer"];
}
}
//Find the number of the next question to be answered based on the user's previous answer and the question they answered
$sqlC = mysql_query("SELECT NextQuestion FROM Answers WHERE QuestionNumber = $sqlALastQuestionAnswered AND PKID = $sqlBAnswer");
//If the operation produces an error, output an error message
if (!$sqlC) {
die('Invalid query for SQLC: ' . mysql_error());
}
//Count the number of rows output
$sqlCCount = mysql_num_rows($sqlC);
//If rows exist, define the values
if ($sqlCCount > 0) {
while ($row = mysql_fetch_array($sqlC)) {
$sqlCNextQuestion = $row["NextQuestion"];
}
}
//Find the question text pertaining to the ID of the next question that needs to be answered
$sqlD = mysql_query("SELECT QuestionText FROM Questions WHERE PKID = $sqlCNextQuestion");
//If the operation produces an error, output an error message
if (!$sqlD) {
die('Invalid query for SQLD: ' . mysql_error());
}
//Count the number of rows output
$sqlDCount = mysql_num_rows($sqlD);
//If rows exist, define the values
if ($sqlDCount > 0) {
while ($row = mysql_fetch_array($sqlD)) {
$SurveyStartedQuestionText = $row["QuestionText"];
}
}
//Set a string of information that will show the question number and question text as appropriate
$ToDisplay = '' . $QuestionNumberReached . ': ' . $SurveyStartedQuestionText . '<br /><br />Answer Text Here';
//If the value for QuestionNumberReached is null, the user has not started the survey
} else if (empty($LastQuestionAnswered)) {
//Find the question text of the first question in the survey
$sql3 = mysql_query("SELECT QuestionText FROM Questions WHERE PKID IN (SELECT FirstQuestion FROM Batch WHERE BatchNumber IN (SELECT BatchNumber FROM User WHERE EmailAddress = '***'))");
//Count the number of rows output
$sql3Count = mysql_num_rows($sql3);
//If rows exist, define the values
if ($sql3Count > 0) {
while ($row = mysql_fetch_array($sql3)) {
$SurveyNotStartedQuestionText = $row["QuestionText"];
}
}
//Set a string of information that will show the question number and question text as appropriate
$ToDisplay = '' . $QuestionNumberReached . ': ' . $SurveyNotStartedQuestionText . '<br /><br />Answer Text Here';
}
}
}
?>
HTML:
<body>
<?php
// Display the concatenated information that has been previously defined
echo $ToDisplay;
?>
</body>
This bit:
if ($StartedQueryCount > 0) {
probably evaluates to false, and there's no matching else tag that adds content.
Try changing:
}
?>
with:
}
else {
$ToDisplay = 'Error: no rows found to display!';
}
?>
Edit:
Also, this bit:
} else if (empty($LastQuestionAnswered)) {
Could be replaced with the more readable:
} else {
Since it does exactly the same thing.
And within your while loop, you are constantly redefining $ToDisplay, I assume this is wanted behaviour? Otherwise initialize the variable on top (before the while() loop) like so:
$ToDisplay = '';
And change the assignments within the loop to concatenations, like so:
$ToDisplay = 'text assignment';
To:
$ToDisplay .= 'text concat'; // look at the dot before =
Thank you for all your help! I really appreciate you all taking the time.
I finally realised what was wrong...
On Line 18 of my PHP code, I had the following:
while ($row = mysql_fetch_array($sql)) {
whereas it should of course have been this:
while ($row = mysql_fetch_array($StartedQuery)) {
Essentially I was calling the rows from the wrong query. And I feel a clot because of it!
Thanks again, everyone :)