PHP beginner with MySQL trouble - php

I am creating a website in which users can log on and review Tablet PC's
On tablet page visitors to the site can see the reviews left by other users. Despite users being able to review 5 tablets, the 'ipad' page for example will only show 'ipad' review. The code can be seen below:
<?php
include('connection.php');
$result = mysql_query("SELECT * FROM tt_review WHERE product = 'Apple iPad'");
echo "<table border='1'>
<tr>
</tr>";
while($row = mysql_fetch_array($result)) //This function is calling the results variable and displaying them within the rows below
{
echo "<tr>"; //this code tells the page to output the table rows that are defined above
echo "<td>" . $row['name'] . "</td>";
echo "<td>" . $row['date'] . "</td>"; //each row is then executed using the table data function
echo "<td>" . $row['product'] . "</td>";
echo "<td>" . $row['star'] . "</td>";
echo "<td>" . $row['comment'] . "</td>";
echo "</tr>";
}
echo "</table>";
?>
I have a field in my database called 'star' which is the rating the users have gave the tablet. 1, 2, 3, 4 or 5 are the options. I need code that works out the average of the 'star' rating from the 'ipad' page and to display an image based on whatever number it is.
All help is greatly appreciated as I am a newcomer and cant seem to find the answer online.
Thanks
Jonathan

Use mysqli to connect to the database. Then you can use the AVG function to calculate average of the column star. Execute the query and fetch the array and then print the average. Then you can use simple switch case or if else to display the image according to the average obtained.
<?php
$db = mysqli_connect("host","user","pass","database");
$query = "SELECT AVG(column_name) FROM table_name";
$result = mysqli_query($db, $query);
$array = mysqli_fetch_row($result);
$average = $array[0];
echo $average;
?>

From what I understand you want to calculate the average rating for each tablet. If yes, you can just fetch the star column for the particular tablet from the database and extract it as an array and run a simple for-each loop to calculate the sum and average of the rating for that tablet and based on the average it calculated, an indication can be placed on the screen in the form of images or something else.

I'm with the others regarding using 'mysql_*' functions, but I won't go into that here as that is not relevant to your question.
To find the average you add all of the total stars together and divide by the quantity. My suggestion is to first find out how many rows are returned.
$totalStars = count($result);
You also need to know what the sum is of the column. This is done using SUM(column). Like so:
$result = mysql_query("SELECT SUM(star) as TotalStars, name, date, product, star, comment FROM tt_review WHERE product = 'Apple iPad'");
However, you can also add a counter to your code, like so:
$x = 0;
while($row = mysql_fetch_array($result)) {
$x += $row['star'];
// your other code
$x++;
}
Finally, at the end, you can display the average by doing something like:
if ($totalStars != 0 ) {
$average = $x / $totalStars;
echo "This product's average stars is " . $average . PHP_EOL;
} else {
// handle the divide by zero issue
}
When it comes to displaying a particular image, well, you can use a conditional statement or something like:
if ($average > 0 && $average <= 1) {
echo "<img src='images/star1.jpg' alt='star1' />";
} else if ($average > 1 && $average <= 1.5) {
// etc etc etc
}
Hope that helped some.

As mentioned, use PDO to connect to the database. Here's how you get the average stars:
$i = 0;
$totalStars = 0;
while($row = mysql_fetch_array($result))
{
$totalStars += $row['star'];
// rest of your code
$i++;
}
echo 'Average stars = '.($totalStars/$i);

As pointed out by others, Mysql has an AVG() function you can use for this exact purpose.
SELECT AVG(star) AS rating FROM tt_review WHERE product = 'Apple iPad' GROUP BY product;
or, to get the star rating for all products you leave off the WHERE
SELECT AVG(star) AS rating FROM tt_review GROUP BY product;
If you just want your rating to be 1,2,3,4, or 5
SELECT ROUND(AVG(star), 0) AS rating FROM tt_review WHERE product = 'Apple iPad' GROUP BY product;
And if you want the rounded number to skew up (a common desire)
SELECT CEILING(AVG(star)) AS rating FROM tt_review WHERE product = 'Apple iPad' GROUP BY product;

Related

How to get record count of an array of objects in PHP

I'm trying to display the total number of records returned from my mongo 3.4 database. For this particular query, the results should be 380 but it's showing 14489. I'm sure it's something simple that I'm missing / forgetting about PHP
Here's the code: (including some debug statements about the type of variable I'm dealing with)
$numrecords = count($records);
echo"<BR><font color=red>".gettype($records)."</font>";
echo"<BR><font color=red>".sizeof($records)."</font>";
if ( $numrecords > 0 ) {
echo "<tr><td colspan='5'><h3>Record Count: ".$numrecords ."</h3></td></tr>";
echo "<tr><th>PH Number</th><th>Department</th></tr>";
foreach ( $records as $rec ) {
if (!empty($rec->department)) {
echo "<tr>";
echo "<td>". $rec->phnum . "</td>";
echo "<td>". $rec->department . "</td>";
echo "</tr>";
}
} //end for
} else {
echo "<tr><td colspan='5'>No matching data</td></tr>";
}
It says the object type is 'array'. I've been playing with count() vs. sizeof()
Any tips would be appreciated.
So it shows the correct number of rows in the table, but the count shows more than what's in the displayed table?
Try to use msqli_num_rows after your query
Here's an example below, you'll have to change it to your needs since you didn't provide your query code
$sql = "SELECT * FROM table_name WHERE datarow='$datarow'";
$result = mysqli_query($conn, $sql);
//this is where you count the number of rows returned from this query.
$count = mysqli_num_rows($result);
If this doesn't work, there's a problem with your query not meeting the specifications that you desire.

PHP - MySQL - Foreach loop bottleneck

I have working code but I seem to have introduced a bad bottleneck to my code. Before I go into detail, let me give you some background on what this code does. I have a table generated in PHP/HTML that shows a list of parts that are in a database (149 parts). The user can select a quantity for that item and click "Add To Cart" which all works fine.
However, I tried to spruce things up a bit by adding in a feature that only allows the user to select the quantity we actually have on hand for this product (before add this feature I previously had the max value hard coded at 100).
Now this does work, but it is TERRIBLY slow (50 seconds to load the page). However, before implementing this the page loaded immediately without a problem, therefore this is definitely a problem with the getPartQuantityOnHand() function.
I think the problem is that for every part (149) I am calling this function that then has to reconnect to the database to find the correct quantity. Does anyone see a way I can improve this? FYI, the parts are hosted on a completely separate database from where the quantity on hand for these parts are hosted.
I have left some parts out of the php code since it was unnecessary bulk for this post, I know that I am missing parts here.
getParts.php
<?php
$partList = $_SESSION['controller']->getParts();
foreach ($partList as $part) {
//Call to get the current quantity on hand for this specific part
//THIS IS WHEN THE PROBLEM WAS INTRODUCED
$quantityOnHand = $_SESSION['controller']->getPartQuantityOnHand($part->number);
//Only display this part if we have at least one on hand
if ($quantityOnHand > 0)
{
echo "<tr>";
echo "<td>" . $part->number . "</td>";
echo "<td>" . $part->description . "</td>";
echo "<td>$" . $part->price . "</td>";
echo "<td>";
echo '<input name="qty'. $part->number .'" type="number" value="1" min="1" max="' . $quantityOnHand .'"/>';
echo "</td>";
echo "</form>";
echo "</td>";
echo "</tr>";
}
}
echo "</table>";
echo "</div>";
?>
getPartQuantityOnHand()
public function getPartQuantityOnHand($partNum) {
$conn = $this->connect();
$sql = "select Quantity from ReceivingInfo where PartNumber = '$partNum'";
$stmt = $conn->prepare($sql);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$quantityOnHand = $row['Quantity'];
return $quantityOnHand;
}
Thanks for any help you can provide!
As the two databases are separate you have two options:
Determine the part numbers before you loop and generate your HTML, then query all at the same time with an IN clause:
SELECT ... WHERE PartNumber IN (1, 2, 3, 4);
Select all stock levels for your parts when you first call getPartQuantityOnHand and store that:
public function getPartQuantityOnHand($partNum) {
if(!$this->partQuantitiesOnHand) {
$conn = $this->connect();
$sql = "select Quantity, PartNumber from ReceivingInfo";
$stmt = $conn->prepare($sql);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
$this->partQuantitiesOnHand = array_column($rows, 'Quantity', 'PartNumber');
}
return $this->partQuantitiesOnHand[$partNum] ?? null;
}
The disadvantage of option 2 is that if you have many more parts than are listed on a single page, it will never perform as well as option 1.
So, instead of doing a 149 different SQL queries, just do one query that brings back all the Quantity values you need.
ex.
SELECT Quantity FROM ReceivingInfo WHERE PartNumber IN ($listOfPartNums)
of course you will have to build the string $listOfPartNums
Or, if you really are always bringing back the full list of them, you can exclude the IN clause and don't need to worry about generating the string.
You'll have to change your function a bit to store the partnum/quantity pairs in an associative array.
Then in your getParts.php get the Quantity like this:
<?php
$partList = $_SESSION['controller']->getParts();
$quantityList = getQtyList(); // return assoc array of partnum/qty pairs
foreach ($partList as $part) {
//Call to get the current quantity on hand for this specific part
//THIS IS WHEN THE PROBLEM WAS INTRODUCED
$quantityOnHand = $quantityList[$part->number];
//Only display this part if we have at least one on hand
if ($quantityOnHand > 0)
{
echo "<tr>";
echo "<td>" . $part->number . "</td>";
echo "<td>" . $part->description . "</td>";
echo "<td>$" . $part->price . "</td>";
echo "<td>";
echo '<input name="qty'. $part->number .'" type="number" value="1" min="1" max="' . $quantityOnHand .'"/>';
echo "</td>";
echo "</form>";
echo "</td>";
echo "</tr>";
}
}
echo "</table>";
echo "</div>";
?>

Add check-box to remove from database in for each loop

I'm learning PHP at the moment, started a practice project to make a todo list.
The list allows the user to enter data into the database with an input field, and uses a while and foreach loop to display the data from the database.
I want to add a check-box to each item displayed that allows the user to check what items on the list they'd like to remove, and for the check-box to have a value corresponding to the id column of the item, then I'll add a submit button that will clear the checked items.
The database table I'm using has two columns an auto increment id column, and a description column.
Here's the loop:
<?php
$query = "SELECT * FROM list_data;";
$list = $mysqli->query($query);
while ($row = $list->fetch_array(MYSQLI_ASSOC)):
echo "<tr>";
foreach($row as $list_item) {
echo "<td>" . $list_item . "</td>";
}
echo "</tr>";
endwhile;
?>
I tried this:
foreach ($row as $id => $description) {
echo "<td>" . $id . $description . "</td>";
}
But for soeme reason this returns the column name, and the values like so:
id1 descriptionTodo List Item Number One.
id2 descriptionTodo List Item Number Two.
id3 descriptionTodo List Item Number Three.
id5 descriptionTodo List Item Number Four.
Can anyone set me on the right path?
I've got the project uploaded onto github if anyone wants to see the whole lot.
Thanks in advance for any help and suggestions.
I don't understand why you are using foreach actually , I would just do this :
<?php
$query = "SELECT * FROM list_data;";
$list = $mysqli->query($query);
while ($row = $list->fetch_array(MYSQLI_ASSOC)):
echo "<tr>";
echo"<td><input type='checkbox' value='".$row['id']."'</td> <td>".$row['description']."</td>";
echo "</tr>";
endwhile;
?>

How to use a mysqli result row more than once in PHP?

I am trying to put together a tool to help me with my upcoming fantasy hockey draft while also learning PHP. I am trying to create multiple lists on a page, one that displays the top 10 available players overall and then others that display the top 10 available players by position.
Here is my SQL query/code
include 'db/connect.php';
$sql='SELECT * FROM players WHERE pick IS NULL';
$players=$conn->query($sql);
if($players === false) {
trigger_error('Wrong SQL: ' . $sql . ' Error: ' . $conn->error, E_USER_ERROR);
} else {
$rows_returned = $players->num_rows;
}
Then later in the page I have a while loop that generates a table with the top ten players
while ($row = $players->fetch_array()) {
if ($i == 10) {
break;
}
echo "<tr>";
echo "<td>" . $row['Rank'] . "</td>";
echo "<td>" . $row['Player'] . "</td>";
echo "<td>" . $row['Team'] . "</td>";
...
And all that works fine. However, when I go to use the same method to generate a list containing only a certain position (C, RW/LW, etc...) it starts off where the top 10 player list ends. (See what I mean here: http://i.imgur.com/JApeftU.png)
I assume this has to do with the $players->fetch_array() however I do not know what the best way would be to get around it.
Any ideas?
Thanks!
Populate rows with all the players.
while ($row = $players->fetch_array()) { //→ $rows = $players->fetch_all();
$rows[] = $row;
}
You can use count() to get total amount of players in the array
$totalPlayers = count($rows);
Now you can loop through the array with for loop
for($i = 0; $i < $totalPlayers; $i++){
//echo out the stuff you want
echo $rows[$i]['player'];
}
Or only ten
for($i = 0; $i < 10; $i++){
//echo out the stuff you want
echo $rows[$i]['player'];
}
Well, for the future visitors, lured by the misleading title, the other answer is okay.
While for you personally, the other answer, as well as your question, is wrong.
And it's your idea on using databases is wrong in the first place.
A database is not like a text file, which you but bound to read every time from first line to last. Databases are quite intelligent and intended to return you the very data you requested.
Think it this way: what if your league will grow up to employ thousands of players. It will burden PHP script with lots of useless info, when it needs only a hundred of players.
So, it seems you need different queries to get differen data sets. First, you need a query
SELECT * FROM players WHERE pick IS NULL ORDER BY field DESC LIMIT 10
To get overall top ten, where field is whatever field you're using to determine the "top" player. And then several queries, each getting players for the certain position.
SELECT * FROM players WHERE pick IS NULL AND position=? ORDER BY field DESC LIMIT 10

Printing data horizontally using php and mysql

I want to print data from the database in a horizontal manner.
I have two table one that holds products names and another that holds products performance by months eg i want data to appear in a table like this
product name,performance by months from january to december
eg
product A,1000 ,2000, etc performance by months
product B,2000,3300, etc performace by months
Edit: I didn't realize you said you have two tables. So the query in my solution should be adapted with a JOIN and ordered, but we cannot dig further into this without knowing your schema. My solution addresses the main concern (i.e. printing results horizontally), provided you obtain two fields to show in two different rows.
Just retrieve your data and store it in a multidimensional array, THEN create the table.
$data = array();
$sql = "SELECT product, performance FROM table";
$rs = mysql_query($sql);
while ($row = mysql_fetch_assoc($rs))
{
$data[] = array($row['product'], $row['performance']);
}
echo "<table><tr>";
// print products in the first line of the table
foreach($data as $d)
{
echo "<td>" . $d[0] . "</td>";
}
echo "</tr><tr>";
// then print performances
foreach($data as $d)
{
echo "<td>" . $d[1] . "</td>";
}
echo "</tr></table>";

Categories