How does this bit of code work? - php

I'm going through Head First PHP and I've found this snippet of code in PHP.
It's supposed to display each row of records from a table containing the first_name, last_name and email.
while($row = mysqli_fetch_array($result))
{
echo $row['first_name'] . ' ' . $row['last_name'] .
' : ' . $row['email'] . '<br />';
}
The $row array contains the next row obtained by mysqli_fetch_array(). But how is this a condition to be checked by the while loop? What exactly does the while loop evaluate to be true/false, before running the inner code? And why exactly does the loop stop when the rows have exhausted? There isn't even a condition to check for an EOF!. So how exactly does this work?

Referring to the PHP Documenation, mysqli_fetch_array() "Returns an array of strings that corresponds to the fetched row or NULL if there are no more rows in resultset." So, when there are no more results, it returns null which evaluates to false and ends the loop.

Related

max() function is disaplying the lowest value

Hello all hope you are doing fine. i have been working on a point system where for each message you get points. everything is working fine until it comes to displaying the highest point to the modal with a table. I looked around the whole
stackoverflow but didnt found a solution, The problem is that I have the highest point of 119... but when I use the MAX function I get the lowest value which is 49.8 and it displays only one result .. and also i would like to get a hint or would like to know how can i select other columns in a query which has that MAX() command. Below is my php , I hope this much information is enough! Thank You...
<?php
$get = $mysqli->query("SELECT * FROM boom_users WHERE user_point > 20 LIMIT 5");
while($row = $get->fetch_assoc()){
echo "<table>";
echo "<tr>";
echo "<td><img class='avatar_menu glob_av' src='https://**********z.com/avatar/" . $row['user_tumb'] . "' ></td>";
echo "<td style='width:90%;' class='username " . $row['user_color'] . "'> " . $row['user_name'] . "</td>";
echo "<td>" . $row['user_point'] . "</td>";
echo "</tr>";
echo "</table>";
}
?>
Most likely explanation for MAX(foo) (SQL aggregate function) returning 49.8 when the expected result is 119 is that foo is defined as character type, rather than numeric.
Using the MAX() aggregate function will also "collapse" all of the rows into a single row. A MySQL-sepcific non-standard extension allows for other expressions in the SELECT list to be returned... the values returned for those expressions is not guaranteed to be from the same row that supplies the value returned for MAX().
Absent a concrete specification, including sample data and example of expected output, it's not possible to make a recommendation for an appropriate query. We're just guessing.
Here's a guess:
SELECT b.*
FROM boom_users b
WHERE ( b.user_point + 0 ) > 20
ORDER
BY ( b.user_point + 0 ) DESC
LIMIT 5
Note: the " + 0 " is a convenient MySQL shorthand to cause conversion of character types into numeric type.

MySql Query results from multiple select form

I have a form on a html page which allows me to select multiple items. The name of the form is name="region[]
It posts to another page where I use this code:
The region(s) selected:
<?php
$values = $_POST['region'];
foreach ($values as $region){
echo $region;
}
?>
This will display the results of the form perfectly; if there is one value it will print the one value, but if there is more than one then it will print them all.
I need to use the results of this in a query:
<?php
$con=mysqli_connect("****","****","****","****");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$result = mysqli_query($con,"SELECT
GoogleBusinessData.BusName,
GoogleBusinessData.BusAddress,
PostcodeTbl.PostcodeFirstTown,
PostcodeTbl.PostcodeFirstArea,
PostcodeTbl.Region,
PostcodeTbl.Postcode,
PostcodeTbl.PostcodeFirstLetters,
PostcodeTbl.PostcodeFirstPart,
PostcodeTbl.Country,
GoogleBusinessData.BusPhone,
GoogleBusinessData.BusCats,
GoogleBusinessData.FaroukCat,
GoogleBusinessData.BusWebsite,
GoogleBusinessData.BusDescription,
GoogleBusinessData.BusGoogleBusinessID,
GoogleBusinessData.BusPageURL,
EmailTable.EmailNumberOfEmails,
EmailTable.EmailAddresses
FROM
GoogleBusinessData
INNER JOIN PostcodeTbl ON GoogleBusinessData.BusPostalCode = PostcodeTbl.Postcode
INNER JOIN EmailTable ON GoogleBusinessData.BusWebsite = EmailTable.EmailWebsite
WHERE EmailTable.EmailNumberOfEmails > 0 AND
GoogleBusinessData.FaroukCat = 'Wedding Planner'
GROUP BY
GoogleBusinessData.BusWebsite
ORDER BY
GoogleBusinessData.BusName ASC
LIMIT 0,20");
while($row = mysqli_fetch_array($result))
{
echo $row['BusName'] . " - " . $row['PostcodeFirstTown'] . " - " . $row['PostcodeFirstArea'] . " - " . $row['Region'] . " - " . $row['Postcode'];
echo "<br>";
}
mysqli_close($con);
?>
So I need to add the condition in the WHERE to only return the results if it contains one of the regions with the form. I tried the following with no joy:
WHERE PostcodeTbl.Region IN ('$region') AND
EmailTable.EmailNumberOfEmails > 0 AND
GoogleBusinessData.FaroukCat = 'Wedding Planner'
But this only returns the last selection (as if there were only one selected).
Can anyone help?
In your first script, you are looping through the items. Each item is put into the variable $region one by one. So after the loop, $region contains the last item. If you construct the where clause at that time, it explains why the query only returns the last item.
To fix this, you'll have to construct a variable (e.g. $regions) that contains a list of regions.
For instance:
$regions = "'" . implode($_POST['region'], "','") . "'";
... WHERE PostcodeTbl.Region IN ('$regions') AND ...
Note that this is potentially unsafe, since the input in $_POST is not validated, so it is better to loop through the array (like you did) and validate each item one by one while constructing the string in $regions. You can use mysqli_real_escape_string for that.
Alternatively, and arguably better, is to use the parameter binding capabilities of mysqli. This is a bit tricky with array variables, but the details on how to do that are already described in this question.

How to display a single row from a database?

So I have been looking for ways to display data from a database. However, they all require a loop and I do not want a loop as I only have 1 row in this table.
I came across mysqli_fetch_row() but I am not sure how to implement this. I am starting to learn PHP and MySQL and so any help is appreciated! This is what I have so far...
$displayIntro = mysqli_query($connection,"SELECT * FROM Introduction");
$displayTitle = mysqli_fetch_row($displayIntro);
echo $displayTitle['Title'];
echo $displayTitle['Description'];
Also after displaying the plain text, how can I format it with HTML? For example, the title will need to be enclosed in <h1></h1> and the subscription in paragraph <p></p>.
Much thanks to any answers!
The problem is mysqli_fetch_row returns enumerated results, array with numeric indexes, so this should be like:
$displayIntro = mysqli_query($connection,"SELECT `Title`,`Description` FROM Introduction");
$displayTitle = mysqli_fetch_row($displayIntro);
echo $displayTitle[0]; // assuming column 'Title' is first row
echo $displayTitle[1]; // assuming column 'Description' is second row
What you should use here is mysqli_fetch_assoc to fetch a result row as an associative array:
$displayIntro = mysqli_query($connection,"SELECT `Title`,`Description` FROM Introduction");
$displayTitle = mysqli_fetch_assoc($displayIntro);
echo $displayTitle['Title'];
echo $displayTitle['Description'];
Use code from #Maximus2012 answer to form html row. Also to get only one row from table with more than one records you can just add LIMIT 1 at the end of the MySQL query like this:
"SELECT `Title`,`Description` FROM Introduction LIMIT 1"
Hope this helps :)
From PHP manual entry for mysqli_fetch_row (link):
"Fetches one row of data from the result set and returns it as an enumerated array, where each column is stored in an array offset starting from 0 (zero)." The function returns an enumerated array, not associative array.
Untested, but I would expect this to work:
echo $displayTitle[0];
echo $displayTitle[1];
$displayIntro = mysqli_query($connection,"SELECT * FROM Introduction");
$displayTitle = mysqli_fetch_row($displayIntro);
echo "<html>";
echo "<body>";
echo "<h1>" . $displayTitle['Title'] . "</h1>";
echo "<p>" . $displayTitle['Description'] . "</p>";
echo "</body>";
echo "</html>";

1st row is not being from database in php

For some reason I'm having a problem retrieving data from my database. It leaves off the first item being listed.
$sql=mysql_query("SELECT * FROM students WHERE (year = '" . mysql_real_escape_string($_SESSION['year']) . "') and ( branch= '" . mysql_real_escape_string(($_SESSION['branch'])). "') ");
$data=mysql_fetch_array( $sql );
print "<table>"
while($data = mysql_fetch_array( $sql ))
{
Print "<tr><td>".$data['idno']." </td><td>".$data['name'] . " </td></tr>";
}
print "</table>"
Please help me with this. Thank you.
Remove the following line:
$data=mysql_fetch_array( $sql );
The call to mysql_fetch_array moves the internal pointer to the next row, thus you are getting all rows except the first in your while loop.
You could also reset the internal pointer with mysql_data_seek.
mysql_data_seek ($sql, 0); // 0 for first row
It's because you use mysql_fetch_array one time before your while. The first call will get the first result, and then you will enter into the while loop. the $datavariable will erase the first result to be assigned by the second result and then the third, the fourth and so on.
Because of this call before the while loop, you will always avoid the first result

PHP print 0 for months not returned by MySQL

I am using google charts API to plot some data. I am grabbing the data from a MySQL database and printing it using MySQL.
<?php
$income_from_clients = $mysql_obj->select ( "
SELECT
sum(invoice.invoice_amount_payable) AS invoice_totals,
company.company_label AS company_label,
MONTHNAME(invoice.invoice_date_paid) AS month,
YEAR(invoice.invoice_date_paid) AS year
FROM invoice INNER JOIN company ON invoice.company_id = company.company_id
WHERE
invoice.invoice_active=1
AND invoice.invoice_status_id=7
AND invoice.invoice_date_deleted=0
AND invoice.invoice_date_paid>='" . $_POST ["start_date_"] . "-" . $_POST ["start_date_month"] . "-" . $_POST ["start_date_date"] . "'
AND invoice.invoice_date_paid<='" . $_POST ["end_date_"] . "-" . $_POST ["end_date_month"] . "-" . $_POST ["end_date_date"] . "'
AND company.company_id=" . $_POST ["company_id"] . "
GROUP BY company.company_id, MONTH(invoice.invoice_date_paid), YEAR(invoice.invoice_date_paid)
ORDER BY YEAR(invoice.invoice_date_paid), MONTH(invoice.invoice_date_paid)" );
echo "data.addRows($mysql_obj->mysql_num_rows);";
$i = 0;
foreach ( $income_from_clients as $ifc ) {
echo "data.setValue($i, 0, '" . $ifc ["month"] . " " . $ifc ["year"] . "');\n";
echo "data.setValue($i, 1, " . $ifc ["invoice_totals"] . ");\n";
$i ++;
}
?>
This is working fine however any months where there has not been an invoice is simply skipped on the chart as it isn't returned returned from the MySQL. How would I get it to plot a 0 for these months?
Thanks.
To fill holes in the data in MySQL, you need to join it with a reference table (calender in your case).
See - Using a Join to Fill in Holes in a List
At the moment, you're iterating over the results from the database and outputting values based on the rows it returns. Since it doesn't return the rows with a value of 0, you won't see those in your output.
Two viable solutions include:
Modify your SQL so that it returns the rows with a value of 0 (see Sukumar's answer)
Change your PHP so that it iterates over the year/month combinations you are interested in and outputs the value from the database or 0 if there isn't one. I'm not sure which ones you are "interested in", but you might be able to iterate FROM "smallest year/monthcombination returned from the db" TO "largest year/monthcombination returned from the db" (or current year/month). If you do this, you'll likely want to iterate through the results in the database and put them in a (year/month -> value) map... then iterate over the dateranges and pull values from the map.

Categories