I have a php file that includes two functions, one to connect to the database and one to set cookied for the cart. Here is that file:
<?php
$dbServer="localhost";
$dbName="test";
function ConnectToDb($server, $database){
$s=#mysql_connect($server);
$d=#mysql_select_db($database, $s);
if(!$s || !$d)
return false;
else
return true;
}
function GetCartId(){
if(isset($_COOKIE["cartId"])){
return $_COOKIE["cartId"];
}
else {
session_start();
setcookie("cartId", session_id(), time()+((3600*24)*30));
return session_id();
}
}
?>
The function for connecting to the database works well in another php file for this particular program. I am having a problem with it in this file:
<?php
include("db.php");
switch($_GET["action"]) {
case "add_item":
{
AddItem($_GET["id"], $_GET["qty"]);
ShowCart();
break;
}
case "update_item": {
UpdateItem($_GET["id"], $_GET["qty"]);
ShowCart();
break;
}
case "remove_item": {
RemoveItem($_GET["id"]);
ShowCart();
break;
}
default: {
ShowCart();
}
}
function AddItem($itemId, $qty) {
// Will check whether or not this item
// already exists in the cart table.
// If it does, the UpdateItem function
// will be called instead
$cxn = #ConnectToDb($dbServer, $dbName);
// Check if this item already exists in the users cart table
$result = mysql_query("select count(*) from cs368_cart where cookieID = '" . GetCartID() . "' and itemId = $itemId");
$row = mysql_fetch_row($result);
$numRows = $row[0];
if($numRows == 0) {
// This item doesn't exist in the users cart,
// we will add it with an insert query
#mysql_query("insert into cs368_cart(cookieID, itemId, qty) values('" . GetCartID() . "', $itemId, $qty)");
}
else {
// This item already exists in the users cart,
// we will update it instead
UpdateItem($itemId, $qty);
}
}
function UpdateItem($itemId, $qty) {
// Updates the quantity of an item in the users cart.
// If the qutnaity is zero, then RemoveItem will be
// called instead
$cxn = #ConnectToDb($dbServer, $dbName);
if($qty == 0) {
// Remove the item from the users cart
RemoveItem($itemId);
}
else {
mysql_query("update cs368_cart set qty = $qty where cookieID = '" . GetCartID() . "' and itemId = $itemId");
}
}
function RemoveItem($itemId) {
// Uses an SQL delete statement to remove an item from
// the users cart
$cxn = #ConnectToDb($dbServer, $dbName);
mysql_query("delete from cs368_cart where cookieID = '" . GetCartID() . "' and itemId = $itemId");
}
function ShowCart() {
// Gets each item from the cart table and display them in
// a tabulated format, as well as a final total for the cart
$cxn = #ConnectToDb($dbServer, $dbName);
$result = mysql_query("select * from cs368_cart inner join cs368_products on cart.itemId =
items.itemId where cart.cookieID = '" . GetCartID() . "' order by items.itemName asc")
or die("Query to get test in function ShowCart failed with error: ".mysql_error());
?>
What can I do the remedy this problem? Thanks!
First: lose the #, and put some proper error handling in there (those functions return false when something goes wrong, and you can use mysql_error and mysql_errno to log it).
Second: mysql_real_escape_string and intval on those $_GET parameters before someone sneaks in some extra code through the URL.
Third: you're accessing $dbServer and $dbName as variables local to the function UpdateItem, rather than global to the script. You should only connect to the database once (in the original db.php file), and let the query functions take care of the rest (since there's only one connection, they all default to that one anyway).
Related
I have a PHP script that is split into two separate PHP scripts (As they each serve a purpose and are quite lengthy). For simplicity let's call these 1.php and 2.php.
Script 1.php does an API call to a website passes the payload to a function. Once has truncated and inserted the new records into the table, it then includes the 2nd script. This is where the issue begins. Seemingly when I query the marketPlace table it returns a null array however if I insert a sleep(1) before I include 2.php it works! I can only summize that somehow the truncate and insert queries in 1.php had not completed before the next queries were called? (I've never come across this before!).
There is only one database connection and is defined by a database class which is contained in 1.php:
class Database
{
// This class allows us to access the database from any function with ease
// Just call it with Database::$conn
/** TRUE if static variables have been initialized. FALSE otherwise
*/
private static $init = FALSE;
/** The mysqli connection object
*/
public static $conn;
/** initializes the static class variables. Only runs initialization once.
* does not return anything.
*/
public static function initialize()
{
Global $servername;
Global $username;
Global $password;
Global $dbname;
try {
if (self::$init===TRUE)return;
self::$init = TRUE;
self::$conn = new mysqli($servername, $username, $password, $dbname);
}
catch (exception $e) {
date('Y-m-d H:i:s',time()) . " Cant' connect to MySQL Database - re-trying" . PHP_EOL;
}
}
public static function checkDB()
{
if (!mysqli_ping(self::$conn)) {
self::$init = FALSE;
self::initialize();
}
}
}
The function that trunctated and inserted into the marketplace is:
function processMarketplace($marketData) {
// Decode to JSON
$outputj = json_decode($marketData, true);
$marketplaceCounter = 0;
// Check for success
if (($outputj['success']==true) && (!stristr($marketData, "error"))) {
// Create the blank multiple sql statement
$sql = "TRUNCATE marketplace;"; // Clears down the current marketPlace table ready for new INSERTS
//Loop through each multicall
foreach ($outputj['multiCall'] as $orderBook) {
foreach ($orderBook['marketplace'] as $orderLine) {
$type = $orderLine['type'];
$price = $orderLine['amountCurrency'];
// Add new SQL record (This ignores any duplicate values)
$sql .="INSERT IGNORE INTO marketplace (type, price) VALUES ('" . $type . "'," . $price . ");";
}
$marketplaceCounter++;
}
// Now run all the SQL's to update database table
if (strlen($sql) > 0) {
if (Database::$conn->multi_query($sql) === TRUE) {
echo mysqli_error(Database::$conn);
//echo "New records created successfully";
} else {
echo mysqli_error(Database::$conn);
echo "Error: " . $sql . "<br>" . Database::$conn->error;
}
}
echo date('Y-m-d H:i:s',time()) . " == Marketplace Orderbook retreived == <BR><BR>" . PHP_EOL;
} else {
echo date('Y-m-d H:i:s',time()) . " Failed to get Marketplace data. Output was: " . $marketData . "<BR>" . PHP_EOL;
die();
}
}
I've chased this around for hours and hours and I really don't understand why adding the sleep(1) delay after I have called the processMarketplace() function helps. I've also tried merging 1.php and 2.php together as one script and this yields the same results. 2.php simply does a SELECT * FROM marketPlace query and this returns NULL unless i have the sleep(1).
Am I missing something easy or am I approaching this really badly?
I should add I'm using InnoDB tables.
This is how its called in 1.php:
$marketData = getData($user,$api); // Get Marketplace Data
processMarketplace($marketData); // Process marketplace data
sleep(1); // Bizzare sleep needed for the select statement that follows in 2.php to return non-null
include "2.php"; // Include 2nd script to do some select statements on marketPlace table
2.php contains the following call:
$typeArray = array('1','2','3');
foreach ($typeArray as $type) {
initialPopulate($type);
}
function initialPopulate($type) {
// Reset supplementary prices
mysqli_query(Database::$conn, "UPDATE marketPlace SET price_curr = '999999' WHERE type='" . $type . "'");
echo mysqli_error(Database::$conn);
// Get marketplace data <--- This is the one that is strangely returning Null (after the first loop) unless I place the sleep(1) before including 1.php
$query = "SELECT * FROM marketPlace WHERE type='" . $type . "'";
$result = mysqli_query(Database::$conn, $query);echo mysqli_error(Database::$conn);
$resultNumRows = mysqli_num_rows($result);echo mysqli_error(Database::$conn);
// Create array from mysql data
$rows = array();
while($r = mysqli_fetch_assoc($result)) {
$rows[] = $r;
}
// Get information from the offertypes table
$query2 = "SELECT offerID FROM queryTypes WHERE type='" . $type . "'";
$result2 = mysqli_query(Database::$conn, $query2);echo mysqli_error(Database::$conn);
// Create array from mysql data
$rows2 = array();
while($r2 = mysqli_fetch_row($result2)) {
$rows2[] = $r2;
}
// Loop through marketplace data and apply data from the offertypes table
$sql1 = ""; // Create a blank SQL array that we will use to update the database
$i = 0;
foreach ($rows as $row) {
$sql1 .= "UPDATE marketPlace SET enrichmentType = " . $rows2[$i][0] . " WHERE type='" . $type . "';";
$i++;
}
// Now run all the SQL's to update database table
if (strlen($sql1) > 0) {
if (Database::$conn->multi_query($sql1) === TRUE) {
echo mysqli_error(Database::$conn);
//echo "New records created successfully";
} else {
echo mysqli_error(Database::$conn);
echo "Error: " . $sql1 . "<br>" . Database::$conn->error;
}
}
}
You are using mysqli:multi_query.
Unlike query, multi_query does not retrieve the results immediately. Retrieving the results must be done using mysqli::use_result
An example from the documentation:
/* execute multi query */
if ($mysqli->multi_query($query)) {
do {
/* store first result set */
if ($result = $mysqli->use_result()) {
while ($row = $result->fetch_row()) {
printf("%s\n", $row[0]);
}
$result->close();
}
/* print divider */
if ($mysqli->more_results()) {
printf("-----------------\n");
}
} while ($mysqli->next_result());
}
You don't need to print the results, but if you don't retrieve them, you are not guaranteed the INSERT has completed.
Note in the documentation for use_result at
https://www.php.net/manual/en/mysqli.use-result.php
it states
"Either this or the mysqli_store_result() function must be called
before the results of a query can be retrieved, and one or the other
must be called to prevent the next query on that database connection
from failing."
As a result of not calling store_result or use_result, you are having unpredictable results.
I have used someone else's code that uses the ipaddress way. However, I would like to use a code that checks for the current userid and the id number.
$ipaddress = md5($_SERVER['REMOTE_ADDR']); // here I am taking IP as UniqueID but you can have user_id from Database or SESSION
/* Database connection settings */
$con = mysqli_connect('localhost','root','','database');
if (mysqli_connect_errno()) {
echo "<p>Connection failed:".mysqli_connect_error()."</p>\n";
} /* end of the connection */
if (isset($_POST['rate']) && !empty($_POST['rate'])) {
$rate = mysqli_real_escape_string($con, $_POST['rate']);
// check if user has already rated
$sql = "SELECT `id` FROM `tbl_rating` WHERE `user_id`='" . $ipaddress . "'";
$result = mysqli_query( $con, $sql);
$row = mysqli_fetch_assoc();//$result->fetch_assoc();
if (mysqli_num_rows($result) > 0) {
//$result->num_rows > 0) {
echo $row['id'];
} else {
$sql = "INSERT INTO `tbl_rating` ( `rate`, `user_id`) VALUES ('" . $rate . "', '" . $ipaddress . "'); ";
if (mysqli_query($con, $sql)) {
echo "0";
}
}
}
//$conn->close();
In your database table, set the user_id column as UNIQUE KEY. That way, if a user tries to cast a second vote, then the database will deny the INSERT query and you can just display a message when affected rows = 0.
Alternatively, (and better from a UX perspective) you can preemptively do a SELECT query for the logged in user before loading the page content:
$allow_rating = "false"; // default value
if (!$conn = new mysqli("localhost", "root","","database")) {
echo "Database Connection Error: " , $conn->connect_error; // never show to public
} elseif (!$stmt = $conn->prepare("SELECT rate FROM tbl_rating WHERE user_id=? LIMIT 1")) {
echo "Prepare Syntax Error: " , $conn->error; // never show to public
} else {
if (!$stmt->bind_param("s", $ipaddress) || !$stmt->execute() || !$stmt->store_result()) {
echo "Statement Error: " , $stmt->error; // never show to public
} elseif (!$stmt->num_rows) {
$allow_rating = "true"; // only when everything works and user hasn't voted yet
}
$stmt->close();
}
echo "Rating Permission: $allow_rating";
And if they already have a row in the table, then don't even give them the chance to submit again.
i have been trying since yesterday, and almost covered all questions regarding this matter in Stackoverflow plus googling, but so far nothing is working with me, i try to check username availability before updating the username in database, however, it wont check and always update the username directly without error message regarding not availability of the name..
here my code
//new connection
$con = new mysqli("localhost", "student", "student", "C14D5");
if ($con->connect_errno) { //failed
echo "Failed to connect to MySQL: (" . $con->connect_errno . ") " . $con->connect_error;
}
//success
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['clientN'])) {
$query = mysqli_query("SELECT client_name FROM clients WHERE client_name='".$_POST['clientN']."'");
if (mysqli_num_rows($query) != 0) {
echo "<script>
alert('Username is not available, please select another username.');
</script>";
header('Location: '. $_SERVER['HTTP_REFERER'] );
} else {
// run sql
$sql ="UPDATE `clients` SET `client_name` = '".$_POST['clientN']."' WHERE `client_ID` = '".$_POST['SelectClient']."'";
if ($con->query($sql) === TRUE) {
echo "<h3> New record created successfully</h3>";
header('Location: '. $_SERVER['HTTP_REFERER'] );
} else {
echo "Error : " . $sql . "<br>" . $con->error;
}
$con->close();
}
}
You can use the mysqli_num_rows() function to avoid data duplication in your database
use this code :
//specify the database connection factors as usual ,then
$uname = $_POST['your_username_field'];
$sql = "SELECT * FROM your_db where username='$uname'";
//the variable 'sql' will store the resultset of the query
$num_row = mysqli_num_rows($sql);
// the 'num_row' will store the number of rows which matches your $sql resultset. So if it is greater than '0' then the data already exists
if( $num_row > 0)
{
// display 'username exists error'
}
else
{
// Insert user name into your database table
}
If the num_rows is greater than 0 ,then the username is already present in your database table . So at that case throw error. else INSERT the user name into your database and display success message .
I have a table with all the product's info.
PRODUCT TABLE
produc_id
product_name
img1
img2
img3
I created a page to update the product's info. My problem is how to manage the images. In the variables img1, img2 and img3 I saved the path of the images. Now i would like to delete that record with a link in the update.php page.
I tried something like this:
<a href="delete_img.php?id=<?php echo $img1; ?>&product_id=<?php echo $product_id; ?>">
the delete_img.php page is:
<?php
include '../asset/inc/auth.inc.php';
include '../asset/inc/db.inc.php';
$db = mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD) or
die ('Unable to connect. Check your connection parameters.');
mysql_select_db(MYSQL_DB, $db) or die(mysql_error($db));
$img1 = (isset($_GET['img1'])) ? $_GET['img1'] : 0;
$product_id = (isset($_GET['product_id'])) ? $_GET['product_id'] : 0;
$query = 'UPDATE product SET img1=NULL WHERE product_id = ' . $product_id;
// invio la query
$result = mysql_query($query);
if (!$result) {
die("Errore nella query $query: " . mysql_error());
}
// close
mysql_close();
header('Refresh: 0; URL=update_immobile.php?id=' . $immobile_id . '');
?>
It works fine, but just for the single variable img1. For the second image, if I want to delete it i need another delete_img.php script (delete_img2.php) and so on.
Question: how can I optimize this 'function'?
You can optimize this function in a lot of different ways. In the $imgid could be the ID of the image stored (1, 2 or 3), therefore the HTML code would look as followed:
<a href="delete_img.php?id=<?=$imgid?>&product_id=<?php echo $product_id; ?>">
With this information submitted you can easily alter your MySQL query in the PHP code.
switch($_GET["id"]) {
case 1:
case 2:
case 3:
$field = "img" . $_GET["id"] ;
break ;
default:
$field = "" ;
}
if($table!="") {
$query = "UPDATE product SET $field=NULL WHERE product_id = $product_id";
$result = mysql_query($query);
}
More suitable would be, if you would create two more tables:
a table which stores the image + path
an intermediary table which links the image to a product
This way a product can store more than only three images and multiple products can have the same image. Also every image gets a unique ID to delete it (which would make your problem easier to solve).
This should work with as many image columns you have (not tested, but you get the idea):
<?php
include '../asset/inc/auth.inc.php';
include '../asset/inc/db.inc.php';
$db = mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD) or
die ('Unable to connect. Check your connection parameters.');
mysql_select_db(MYSQL_DB, $db) or die(mysql_error($db));
$img = (isset($_GET['img1']) && in_array(key($_GET['img1'], array('img1', 'img2', 'img3')))) ? key($_GET['img1']) : 0;
$product_id = (isset($_GET['product_id'])) ? (int)$_GET['product_id'] : 0;
if ($img !== 0) {
$query = 'UPDATE product SET ' . $img . '=NULL WHERE product_id = ' . $product_id;
// invio la query
$result = mysql_query($query);
}
if (!$result) {
die("Errore nella query $query: " . mysql_error());
}
// close
mysql_close();
header('Refresh: 0; URL=update_immobile.php?id=' . $immobile_id . '');
?>
Some notes:
* don't forget to validate user input (I made some small tweaks to the code)
* always use exit or die after sending a redirect header, otherwise anyone could access your admin area with no username/password required
$img1 = (isset($_GET['img1'])) ? $_GET['img1'] : 0;
$img2 = (isset($_GET['img2'])) ? $_GET['img2'] : 0;
$img3 = (isset($_GET['img3'])) ? $_GET['img3'] : 0;
$query = 'UPDATE product SET if($img1==0) img1=NULL' ;
$query .= 'if($img2==0) ,img2=NULL' ;
$query .= 'if($img3==0) ,img3=NULL' ;
$query .= 'WHERE product_id = ' . $product_id'
$result = mysql_query($query);
It is simply concatenation of query with if condition.
I want to update a column in a table in mysql. Basically the column is the flag for the entries of that db table.
The modification of the column is resetting all values to 0 and setting the desired row to 1, for this reason I have post.php file which looks like
<?php
require_once('class.uuid.php');
$connection = mysql_connect("---logindetailshere---");
$db = mysql_select_db("---dbnamehere---",$connection);
switch($_REQUEST['action']){
case ...
break;
case ...
break;
case 'changeDisp':
changeDisp($_REQUEST['uid']);
break;
}
mysql_close($connection);
...
function changeDisp($uid){
global $connection, $db;
$q_string = "UPDATE Questions SET Displayed = 0";
$query = mysql_query($q_string,$connection) or die( sendError(mysql_error() . '<br/><br/>' . $q_string) );
$q_string = "UPDATE Questions SET Displayed = 1 WHERE Uid='${uid}'";
$query = mysql_query($q_string,$connection) or die( sendError(mysql_error() . '<br/><br/>' . $q_string) );
}
?>
on the webpage I display the items and radiobuttons next to the items, the purpose is to select the radiobuttons and post to set the flag 1 for the selected item, for this reason I have a item.php file
<?php
$i = 1;
foreach ($qitem as &$q) {
$options = explode(";", $q["Options"]);
$displayed = '';
if ($q["Displayed"] == 1) { $displayed='checked="yes"'; }
echo("<div class='item' name='".$q["iUid"]."'>");
echo("<div class='count'>".$i.".</div>");
echo ("<div class='radio'><input type='radio' onclick='changeDisp("".$q["Uid"]."")' name='disp' ".$displayed."></div>");
echo("<div class='left'>");
echo("<h4>".$q["Value"]."</h4>");
echo("<div class='details'>Typ: ".$q["Type"]."</div>");
echo("<div class='details'>Skala: ".$options[0]." / ".$options[1]."</div>");
echo("</div>");
echo("</div>");
$i++;
}
?>
here I am using radiobuttons to select the related item, I checked the unique id values using firebug the values are fine, I just want to click on any radiobutton and want to trigger the onclick=changeDisp() function.
I have no idea why the page doesn't reload itself and change the selected flag to 1. Could you please help me to solve this problem?
Thanks in advance.
You cannot use an onclick function to call php function without going there with a javascript, jQuery or ajax call. You could create an ajax script to call the post.php From the item.php page and return the results to you.
Here is an example of creating the function you want. This assumes that $uid is coming from a radio button and not an actual user input. If the user can directly input something you need to use a prepared statment
function changeDisp($uid)
{
$Mysqli = new mysqli(DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME);
if ($Mysqli->connect_errno)
{
echo "Failed to connect to MySQL: (" . $Mysqli->connect_errno . ") " . $Mysqli->connect_error;
$Mysqli->close();
}
$query = "UPDATE Questions SET Displayed = 1 WHERE Uid='".$uid."'";
$update = $Mysqli->query($query);
if($update)
{
return true;
}
return false;
}