echo a sum then work it out - php

In a table i have sums ie 1+1, im trying to make the code work the answer out and check it against the answer given by the end user.
Code
$stmt = $db->prepare("select * from exams where username = :username");
$stmt->execute(array(':username' => "$username"));
$row = $stmt->fetch();
$stmt->execute();
$question1 = $row['q1'];
foreach( $stmt as $row )
{
echo "q1<td>" . $row['q1'] . "</td>";
echo "<td>" . $row['q1a'] . "</td>";
echo "<td>Correct = " . $question1 . "</td>";
}
Table information on the row q1
type = text
the varibles
$row['q1'] = 1+1
$row['q1a'] = there answer
$question1 = the right answer
i have tried $question1 = $row['q1'];
and the output is always the sum in the table.
is there a way to echo the sum (in my table) out and find the value?

PHP will not automatically work out the answer to the given question as this is currently stored as a string, you would first need to split the string into each individual part of the sum. You may wish to read more into the explode function.
Once the string is exploded into its parts (see example below) you can then add the two individual parts together to get the answer you were originally seeking:
$questionParts = explode('+',$row['q1']);
$answer = $questionParts[0] + $questionParts[1];

Related

Pagination script doesn't work with datatables

I've been dealing with tihs problem for more than two days but still couldn't find what's the problem. I am trying to build a pagination system for my search results. Code works perfectly fine when I run it in new php file but when it comes to display those result in a table I constantly keep getting that Error! message inside of the last else section. Plus, wherever I place for loop for page numbers it always showing before the table. Think I was so busy with dealing with this problem I am focusing to the same point. Help, please!
edit I've just deleted all conditional statements and got undefined index for all my variables that I get by POST method. That's the problem but still don't know what might be the solution for this.
<?php
if (isset($_POST['search_btn'])) {
include_once "db_connect.php";
$from = $_POST['from'];
$where = $_POST['where'];
$date = $_POST['date'];
$type = $_POST['type'];
$proc_id = $_POST['proc_id'];
if(empty($from) || empty($where) || empty($date) || empty($type)){
header("Location: index.php?search=empty");
exit();
}else{
//define how many results you want per page
$results_per_page = 10;
//number of results stored in database
"SELECT * FROM proc WHERE p_from = '".$from."' and p_where = '".$where."' and type= '".$type."' ";
$result = mysqli_query($conn, $sql);
$number_of_results = mysqli_num_rows($result);
//determine number of total pages available
$number_of_pages = ceil($number_of_results/$results_per_page);
//determine which page number visitor is currently on
if (!isset($_GET['page'])) {
$page = 1;
} else {
$page = $_GET['page'];
}
//determine the SQL LIMIT starting number for the result on the displaying page
$this_page_first_result = ($page-1)*$results_per_page;
//retrive selected results from database and display them on page $sql='SELECT * FROM proc LIMIT ' . $this_page_first_result . ',' . $results_per_page;
$result = mysqli_query($conn, $sql);
while($rows = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
echo '<tr onclick="content(\''. $rows['proc_id'] .'\')">';
echo "<td>" .$rows['p_name'] . " " . $rows['p_surname']. " </td>";
echo "<td>" .$rows['p_from']. "</td>";
echo "<td>" .$rows['p_where']. "</td>";
echo "<td>" .$rows['p_date']. "</td>";
echo "<td>" .$rows['price']. "</td>";
echo "<td>" .$rows['type']. "</td>";
echo "</tr>";
}
}
//display the links to the pages
for ($page=1;$page<=$number_of_pages;$page++) {
echo '' . $page . ' ';
}
}else{
echo "Error!";
}
?>
I'm just going to assume that the initial display works, but that pagination is giving you problems?
You're using POST values to pass the data from the search form to your code, however, when you then click the pagination links you are transferred to the search page, and lose those values.
You could change the next page URL to be a form and you pass each necessary value as a hidden input field. However, this has the drawback that when you hit the back button in your browser that it'll complain and ask you to resubmit the form data.
Another solution would be to store these post params in a session, cookie, whatever really. But in my opinion, that's not too great of a solution for this issue either.
I'd suggest you use GET parameters and then pass those in the next page button as well. This has the added benefit of being able to bookmark your searches.
Good luck!
As a side note, instead of building your query using concatenation you should use prepared statements. See the docs for the functions I used in the converted code below: https://www.php.net/manual/en/class.mysqli-stmt.php
if ($statement = mysqli_prepare($conn, "SELECT * FROM proc WHERE p_from = ? AND p_where = ? AND type = ?")) {
mysqli_stmt_bind_param($statement, "s", $from);
mysqli_stmt_bind_param($statement, "s", $where);
mysqli_stmt_bind_param($statement, "s", $type);
$result = mysqli_stmt_get_result($statement);
}

Query with multiple OR terms in WHERE returns the whole table

Can anyone tell me why this SQL command does not work?
I have a form with multiple inputs i.e. (id)=> account number, then firstname, lastname and email. I want to allow the user to search anyway they want.
if I leave the code the way it is "with AND" .. when searching only for just the (id) then it will just display the ID row but it won't display the rest of the searches if I try to enter first, last or email, but if I change it to "OR", then all the other input boxes will work displaying the single result, but if I enter just the id "account number" I will display every single customer in my table.. why?
what am I missing so my code can search for all the inputs?
Thank you
$firstname = $_POST['firstname'];
$lastname = $_POST['lastname'];
$email = $_POST['email'];
$firstname = "%$firstname%";
$lastname = "%$lastname%";
$email = "%$email%";
$id = $_POST['id'];
$stmt = $conn->prepare("
SELECT * FROM `Demo_Guests`
WHERE
firstname LIKE :firstname
AND lastname LIKE :lastname
AND email LIKE :email AND id = :id
");
$stmt->bindValue(':id', $id, PDO::PARAM_INT);
$stmt->bindValue(':firstname', $firstname,PDO::PARAM_STR);
$stmt->bindValue(':lastname', $lastname,PDO::PARAM_STR);
$stmt->bindValue(':email', $email,PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_OBJ);
foreach($result as $row){
echo "<tr><td>
" . $row->id . "<br></td>";
echo "<td>" . $row->firstname . "</td>";
echo "<td>" . $row->lastname . "</td>";
echo "<td>" . $row->email . "</td>";
echo "<td>" . $row->reg_date . "</td></tr>";
}
To expand on my comment above, which was:
When you use the OR statement, you need to be sure you don't have firstname LIKE '%%', because that will match everything. You will need to build your query to only use non-empty values provided from the form.
What that means is you will have to build your query from the NON-EMPTY inputs from your search form, and leave out terms that would match everything in your table.
It might be good to start by going through the post data and lifting out the non-empty values, to put in an array:
$searchFields = [];
foreach (['id', 'firstname', 'lastname', 'email'] as $searchField) {
if (!empty($_POST[$searchField])) {
$searchFields[$searchField] = $_POST[$searchField];
}
}
That gives you a list of all the fields that the user actually filled in. You will need that list twice - once to build the query, and once to do the bindings.
if (count($searchFields) > 0) {
$queryStr = "SELECT * FROM `Demo_Guests` WHERE 0";
foreach (array_keys($searchFields) as $fieldName) {
$queryStr .= " OR " . $fieldName . " LIKE :" . $fieldName;
}
// ... the rest of the code goes here
} else {
return "you gotta give me something to work with!";
}
Two notes: 1) I didn't make id a special case, and you will need to do that in your code. 2) WHERE 0 is a lazy-man shortcut to you don't have to do any extra logic later to decide whether you need to add OR to the first term. It turns into WHERE 0 OR firstname LIKE '%Alice%', which is functionally the same as WHERE firstname LIKE '%Alice%'.
Once you build your query string, you can prepare it the way you did above, then perform the bindings with the same array you used to construct the query.
$stmt = $conn->prepare($queryStr);
foreach($searchFields as $fieldName => $fieldValue) {
$stmt->bindValue(':'.$fieldName, "%$fieldValue%", PDO::PARAM_STR);
}
$stmt->execute();
As above, I did not create the code to treat the id field differently, but you should be able to handle that. If you had lots of fields of different types, you might want to change the structure of $searchFields to include type information. If id is the only exception, it's probably easiest to just use an if statement in each loop.
Added:
This search will return all records from the database that match ANY of the input criteria. So if the user searches for firstName LIKE '%Ali%' OR lastName LIKE '%Smi%' you might get back Alice Smith, Alicia Smith, Fred Smith, and Alice Jones.
If, however, you only want that search to return Alice Smith and Alicia Smith, rather than use OR, you use AND. The search will produce fewer results, so it is a little less forgiving for mis-typed names and so forth.
The only other modification to the code is that the lazy-man shortcut also has to change:
if (count($searchFields) > 0) {
$queryStr = "SELECT * FROM `Demo_Guests` WHERE 1";
foreach (array_keys($searchFields) as $fieldName) {
$queryStr .= " AND " . $fieldName . " LIKE :" . $fieldName;
}
// ... the rest of the code goes here
} else {
return "you gotta give me something to work with!";
}
WHERE 1 AND first_name LIKE '%Ali%' is functionally the same as WHERE first_name LIKE '%Ali%'.
Note that in this case, if the user specifies an ID, you will want to ignore the other search fields entirely. Otherwise, if they specify an id and a name that do not match, they won't get back any results at all.

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>";
?>

Need to Count results of a list created in PHP

Okay I have a list being populated and echoed out on a page.
$sql = "SELECT * FROM `game_toe` WHERE `owner`='$mech_units'";
$mydata = mysql_query($sql);
while($record = mysql_fetch_array($mydata)){
echo "<td>" . $record['units'] . "</td>";
Now the results fluctuate depending on the number of 'mech_units' there are. What I need is to display how many are being displayed in the list. Any suggestions?
you can use built in function mysql_num_rows($mydata). This will give you the total number of records that are fetched.
First of all, I would suggest using mysqli.
You could declare a variable which increases by one every time you echo a 'mech_unit'.
$sql = "SELECT * FROM `game_toe` WHERE `owner`='$mech_units'";
$mydata = mysql_query($sql);
$i = 0;
while($record = mysql_fetch_array($mydata)){
$i++;
echo "<td>" . $record['units'] . "</td>";
}
echo "There are " . $i . " mech_units.";
Another option would be to use the mysql_num_rows() function.

Need to Sum results of a list created in PHP

Okay I have list being populated and echoed out on a page
$sql = "SELECT * FROM `game_toe` WHERE `owner`='$mech_units'";
$mydata = mysql_query($sql);
while($record = mysql_fetch_array($mydata)){
echo "<td>" . $record['upkeep'] . "</td>";
Now the results fluctuate depending on the number of 'mech_units' there are. What I need is to display the sum of the Upkeep of the units being displayed. Any suggestions?
You can use array_sum function
$sql = "SELECT * FROM `game_toe` WHERE `owner`='$mech_units'";
$mydata = mysql_query($sql);
$upkeep = []; // Empty array to store all retreived values
while($row = mysql_fetch_array($mydata)){
echo "<td>" . $row['upkeep'] . "</td>";
$upkeep[] = $row['upkeep']; // Fill array with your values
}
echo array_sum($upkeep); // Now just coun array sum from temporary array
EDIT: I made some edit to fit your exact needs.

Categories