sporadic unwanted null entries in database $_GET - php

I have a little temperature protocoling web app, where degrees get adjusted on a page and saved in a database.
It works, but sometimes sporadic errors occur from users which I can't reproduce!
Sometimes there are null-entries in the database and I don't know how and why. It "nulls" the hole row (several temperatures per day are selectable).
If e.g. no temp got selected in a div string "NA" should be handed to the db. This bug is so resilient, I don't know where else to turn to.
Ajax increases Values by clicking on Arrow
$(".arrow_up").die('click');
$(".arrow_up").live('click',function() {
var value = $("#temp_"+this.id).html();
if (value=="NA") {value=$("#istemp_"+this.id).html()}
var newValue = parseInt(value)+ 1;
hands Values over to server
$(document).ready(function() {
$('#save').die('click');
$("#save").live('click',function() {
var tempA=$("#temp_itemA").html();
var tempB=$("#temp_itemB").html();
PHP has to store it
I look if it isn't empty nor that the string null gets handed over. Last one throws Error.
<?php
if((!isset($_GET['tempA'])) || (!isset($_GET['tempB'])) || ($_GET['tempA']!='null')
{
echo "values are missing";
}
else
{
error_reporting(E_ALL);
try {
$dbh = new PDO('sqlite:/var/www/xxx.sqlite');
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$date=date("Y-m-d",time());
$sql = "SELECT * FROM tableTemp WHERE date='".$date."'";
$result = $dbh->query($sql);
foreach($result as $row) {
$id = $row['id'];
}
if (!empty($id)) {
$sql = "UPDATE tableTemp SET tempA='".$_GET['tempA']."',tempB='".$_GET['tempB']"'";
$result = $dbh->query($sql);
}
else {
$sql = "INSERT INTO tableTemp ('tempA','tempB')";
$result = $dbh->query($sql)
?>
I mean, this is as simple as it gets. I can only imagine the trasmitting errors might have something to do with WIFI and packet loss.
How can I can stop inserting (discarding) these pesky null string into the db and throw an error, so that the user has to try it again? My !isset does not work since it isn't empty

Note this is probably stating the obvious
But can you not stipulate that the column in the DB requires a value that is not null then catch the error on the insert
have you seen this answer?
https://stackoverflow.com/a/2103256/1479565

Related

PHP always reports SQL success even when it fails

This is a simple one, maybe I'm having a long brain fart or something, but whats happening is the form is used to set a record only if the name and their cpukey matches then it will continue, as this is a public page with no login, it would be rather annoying for people to be changing other peoples things without knowing 2 sets in information. So the problem here is, the function itself actually works flawlessly, the Message produced which states SUCCESS or FAILURE always produces SUCCESS, even if the function failed (due to no match on one or more rows)
Here is the code used.
if(isset($_POST['upduserNotify'])){
$ccurrentname = mysqli_real_escape_string($con, $_POST['ccnameVal']);
$cclientnotify = mysqli_real_escape_string($con, $_POST['cnotifyVal']);
$cclientcpuk = mysqli_real_escape_string($con, $_POST['ccpukeyVal']);
$changenot = "UPDATE clients SET notify = '$cclientnotify' WHERE cpukey = '$cclientcpuk' AND name = '".$_POST['ccnameVal']."'";
if (mysqli_query($con, $changenot)) {
echo'<div align ="center" style="color:#000000">Your Custom notification was updated successfully</div><br />';
} else {
echo'<div align ="center">You entered an incorrect CPUKEY/Name or used an invalid character</div><br />';
}
}
An UPDATE query that runs, but finds no rows to update, is still a successful one - it ran to completion without encountering any errors, so mysqli_query will return TRUE, per the docs. (If it were a SELECT sort of query, it'd return a mysqli_result object.)
If you want to do something different when it didn't find any rows to update, you'll want to look at the number of affected rows and act accordingly.
if(isset($_POST['upduserNotify'])){
$ccurrentname = mysqli_real_escape_string($con, $_POST['ccnameVal']);
$cclientnotify = mysqli_real_escape_string($con, $_POST['cnotifyVal']);
$cclientcpuk = mysqli_real_escape_string($con, $_POST['ccpukeyVal']);
$changenot = "UPDATE `clients` SET `notify` = '$cclientnotify' WHERE `cpukey` = '$cclientcpuk' AND `name` = '$ccurrentname'";
if (mysqli_query($con, $changenot) && mysqli_affected_rows($con) == 1 )
{
echo'<div align ="center" style="color:#000000">Your Custom Xnotify was updated successfully</div><br />';
}
else if (mysqli_query($con, $changenot) && mysqli_affected_rows($con) == 0 )
{
echo'<div align ="center">You entered an incorrect CPUKEY/Name or used an invalid character</div><br />';
}
}

Query isn't inserting into database [duplicate]

This question already has answers here:
Can I mix MySQL APIs in PHP?
(4 answers)
Closed 6 years ago.
I am attempting to implement a click count system. I am using the following code in this link Click here to see code, but changing it to modern standards. Initially I received errors for the msqli_real_escape_ string, but I believed I resolved it(no errors). Now, I am not receiving any errors at all, but the query is not sending into my database. I am using ini_set('display_errors', 1);
error_reporting(E_ALL); for error checking. Also I have my $con and session in and ini file that I call, so the session and connection are not issues.
Does anyone see what I am doing wrong or is there a good way I can check to see what isn't working?
//create current page constant
$curPage = mysqli_real_escape_string($con,htmlspecialchars($_SERVER['PHP_SELF']));
//set number of clicks variable to 0
$clicks = 0;
//do not recount if page currently loaded
if($_SESSION['page'] != $curPage) {
//set current page as session variable
$_SESSION['page'] = $curPage;
$click_sql = "
SELECT *
FROM click_count
WHERE page_url = ?
";
if (!$click_stmt = $con->prepare($click_sql)) {
$click_stmt->bind_param("s", $curPage);
$click_stmt->execute();
$num_rows = $click_stmt->fetchColumn();
if (!$click_stmt->errno) {
// Handle error here
}
$stmt->bind_result($click_id, $page_url, $page_count);
} elseif ($num_rows == 0) {
//try to create new record and set count for new page to 1
//output error message if problem encountered
$click_insert_stmt = "
INSERT INTO click_count
(page_url, page_count)
VALUES(?, ?)";
if(!$click_stmt = $con->prepare($click_insert_stmt)) {
$click_insert_stmt->execute(array('$curPage',1));
echo "Could not create new click counter.";
}
else {
$clicks= 1;
}
} else {
//get number of clicks for page and add 1 fetch(PDO::FETCH_BOTH)
while($click_row = $click_insert_stmt->fetch(PDO::FETCH_BOTH)) {
$clicks = $row['page_count'] + 1;
//update click count in database;
//report error if not updated
$click_update_stmt = "
UPDATE click_count
SET page_count = ?
WHERE page_url = ?
";
if(!$click_stmt = $con->prepare("$click_update_stmt")) {
$click_update_stmt->execute(array('$clicks', '$curPage'));
echo "Could not save new click count for this page.";
}
}
}
}
Edit: New Updated Code
// ********Page count************
//create current page constant
$curPage = mysqli_real_escape_string($con,($_SERVER['PHP_SELF']));
//set number of clicks variable to 0
$clicks = 0;
//do not recount if page currently loaded
if($_SESSION['page'] != $curPage) {
//set current page as session variable
$_SESSION['page'] = $curPage;
$click_sql = "
SELECT *
FROM click_count
WHERE page_url = ?
";
if (!$click_stmt = $con->prepare($click_sql)) {
$click_stmt->bind_param("s", $_SERVER['PHP_SELF']);
$click_stmt->execute();
$num_rows = $click_stmt->fetchColumn();
if (!$click_stmt->errno) {
// Handle error here
}
$stmt->bind_result($click_id, $page_url, $page_count);
} elseif ($num_rows == 0) {
//try to create new record and set count for new page to 1
//output error message if problem encountered
$click_insert_stmt = "
INSERT INTO click_count
(page_url, page_count)
VALUES(?, ?)";
if(!$click_stmt = $con->prepare($click_insert_stmt)) {
$click_insert_stmt->execute(array($curPage,1));
echo "Could not create new click counter.";
}
else {
$clicks= 1;
}
} else {
//get number of clicks for page and add 1 fetch(PDO::FETCH_BOTH)
while($click_row = $click_insert_stmt->fetch(PDO::FETCH_BOTH)) {
$clicks = $row['page_count'] + 1;
//update click count in database;
//report error if not updated
$click_update_stmt = "
UPDATE click_count
SET page_count=page_count+1
WHERE page_url = ?
";
if(!$click_stmt = $con->prepare("$click_update_stmt")) {
$click_update_stmt->execute(array($curPage));
echo "Could not save new click count for this page.";
}
}
}
}
It looks like you're doing a lot of stuff like this:
$click_update_stmt->execute(array('$clicks', '$curPage'));
I'm not sure where you picked up this habit of quoting variables as strings, but you need to drop it. '$x' and $x are two hugely different things. In the first case it's literally '$x' and in the second case it's whatever the $x variable happens to represent.
Fix it like this:
$click_update_stmt->execute(array($clicks, $curPage));
Also since you're using prepared statements, which by the way is great, you do not need to and should not manually escape your values. Applying them to placeholders with bind_param is the safe way of doing it. Doing any other escaping mangles the data.
Just bind directly to the source:
$click_stmt->bind_param("s", $_SERVER['PHP_SELF']);
Don't arbitrarily run things like htmlspecialchars on input out of paranoia or because you're doing cargo-cult programming and you saw it done in a YouTube tutorial somewhere. That function is intended to be used to display values only, not store them. Data in your database should be as raw as possible.
There's a lot of problems with this code, and one of them that has me confused is why there's so much code. Remember SELECT * and then binding results to arbitrary variables is trouble, your schema might change and then your code is out of sync. Whenever possible fetch rows as an associative array if doing this, then all you have to worry about is renamed ore removed columns.
The biggest problem is this is subject to race conditions because it doesn't use an atomic increment. When writing counters, always do your updates as operations that are a single statement:
UPDATE click_count SET page_count=page_count+1 WHERE page_url=?
Your approach of reading the count, incrementing it, and then writing it back into the database means that you're inviting problems if another operation runs concurrently, something very likely on click-counter code.

php statement for multiple users not working

I am helping in some PHP design for a friends text game and have come to a stump.
I have scheduled a cron job to call the following page / following code, which is working correctly
<?php require("connect.php"); ?>
<?php
$sql = "SELECT id, name, health FROM users";
$query = mysql_query($sql) or die(mysql_error());
$row = mysql_fetch_object($query);
while($row = mysql_fetch_object($query)) {
$id = htmlspecialchars($row->id);
$name = htmlspecialchars($row->name);
$health = htmlspecialchars($row->health);
$sql = "SELECT * FROM property WHERE living='1' AND ownerid='$id'";
$query = mysql_query($sql) or die(mysql_error());
$row = mysql_fetch_object($query);
while($row = mysql_fetch_object($query)) {
$OwnerName = htmlspecialchars($row->ownername);
$OwnerID = htmlspecialchars($row->ownerid);
$RaidPropBonus = htmlspecialchars($row->raidperc);
$RaidPropMoney = htmlspecialchars($row->raidcash);
$PropertyLvl = htmlspecialchars($row->proplvl);
$Living = htmlspecialchars($row->living);
if($PropertyLvl == '5' && $Living == '1'){
if($health < '100'){
$result = mysql_query("UPDATE users SET health=$health + '1' WHERE id='$id'")
or die(mysql_error());
} else { }
} else { }
}
}
?>
Although this only works for ONE user only. I cannot understand why this is. Any other logged in / out accounts that have met the criteria have been ignored. I can maybe only think I am missing a loop? As the ID that is being met first is number 1 and it has stopped there?
Anybody advice at all maybe?
UPDATE - It seems correct I need to get a loop in there, but am so far failing to get this loop working correct. No matter where I seem to amend / add a loop it does not help. Please may somebody suggest anything?
UPDATE2 - As requested, updated with the new version of loop
For what I've understood, the loops should be made on the mysql_fetch_object that will get the each row from the query.
Take a look at the snippet
<?php
require("connect.php");
// here prepare the $userQuery (the one that fetches all users)
// then the first loop that will read each usew row
// AFAICT this should afect all script
while($userRow = mysql_fetch_object($userQuery))
{
// prepare data fetched from the $userQuery
// prepare the $propertyQuery (the one that fetches all properties of the user)
// then the second loop to read all user property rows
// and this will afect the updates
while($propertyRow = mysql_fetch_object($propertyQuery))
{
// prepare data fetched from $propertyQuery
// add logic here
}
}
?>
Also #Matthew Carpenter had a valid point, that mysql_* is deprecated, you should consider in using mysqli_*, or in my opinion take a look at PDO

PDO best way to check if 300+ values exist in database

I have a time dependent script I am working on and used microtime() to find the bottle neck. I determined the time increase is caused by doing a check on 300+ values to see if they exist in a database one at a time at 0.04 seconds a query.
The background of the script is it is a caching script. I need to see if it exists in the DB so I need a true/false (obtained by a rowCount) but i also need a way to relate a false to a value so I can update it. I know using a WHERE tag IN (:ARRAY) would work faster than the individual calls, but I cant think of a way to apply an association of true/false to value in this method.
My current code is below:
//loop through all our values!
//prepare out reusuable statement
$stmt = $db->prepare("SELECT * from cache WHERE value=?");
foreach($values as $tempVal)
{
//find if its in the database
try
{
$stmt->execute(array($tempVal));
$valCount = $stmt->rowCount();
} catch(PDOException $ex) {
echo "PDO error send this to us: " . $ex->getMessage();
}
//update flag
$addToUpdate = 1;
//if its in the database
if($valCount > 0)
{
//get the tag data
$valRes= $stmt->fetch();
//check if cache expired
$addToUpdate = 0;
}
//add to update list
if($addToUpdate)
{
//needs updating
$updateList[] = $tempVal;
//add to not in DB list to minimize queries
if($tagTCount == 0)
{
$notInDB[$tempVal] = $tempVal;
}
}
Any suggestions? I can explain more if anything is not clear.
Thank you,
Nick
So you just issue your query with the complete array, using the IN (?,?,?,?,?...) list:
// abstract, use a PDO wrapper of your choosing
$query = db("SELECT * FROM cache WHERE value IN (??)", $values);
Then iterate over the result list. Only matched $values will return. So build your first list from that:
foreach ($query as $row) {
$updateList[] = $row["value"];
}
To get the list of absent entries, just diff that against your original array:
$notInDB = array_diff($values, $updateList);
You could of course use a second NOT IN query. But doing that differentiation in PHP is simpler.

php mysql fetch statement fetching issue

i have a problem my script has three mysql_query which should be used after each other , i am trying to create a script that reserve tickets by changing their status from sold = "No" to "Yes", the script count the number of tickets user has entered on html form which give the server side a variable with number of tickets called = $tickets.
hint : this is such a model so no need for mysql injection security
here is my code :
//get ticket status
$eventTicket = mysql_query("SELECT eventTickets FROM beventreservation WHERE eventId = '$eventId'") or die(mysql_error());
$ticketrow = mysql_fetch_array($eventTicket) or die(mysql_error());
//test... which is working !
echo $ticketrow['eventTickets'];
//get classId from classes
$selectClass = mysql_query("SELECT classId FROM quotaclasses WHERE className = '$classes' AND eventFK = '$eventId'") or die (mysql_error());
$classrow = mysql_fetch_array($selectClass) or die(mysql_error());
//this var is to define which class the user used
$choosedClass = $classrow['classId'];
//test ... which did not work !!!
echo $classrow['classId'];
if ($ticketrow['eventTickets'] == "Yes")
{
for($counter=1;$counter<$numberOfTickets;$counter++)
{
$bookTicket = mysql_query("UPDATE unites SET ticketSold = 'Yes' WHERE businessreservationIdFk = '$eventId' AND classIDfk ='$choosedClass'") or die(mysql_error());
echo "ticket ". $counter . " done !";
}
}
the script doesn't fetch this syntax, and there is no errors showed on my page !
$classrow = mysql_fetch_array($selectClass) or die(mysql_error());
also , i tried to echo the variable $tickets after this syntax , it did not showed up, is there a problem to fetch more than mysql_query on the same script page ? tell me where do i go wrong here please .
Don't call die() in conjunction with a mysql_fetch_*() call. If there are no rows returned, mysql_fetch_array() returns FALSE, which triggers your die() and kills your script even though there was no error. Since you have already don error checking on $selectClass in the mysql_query() call, you know it has succeeded.
// This query returned no rows, but was successful syntactically and functionally.
$selectClass = mysql_query("SELECT classId FROM quotaclasses WHERE className = '$classes' AND eventFK = '$eventId'") or die (mysql_error());
Instead, test if rows were returned:
if (mysql_num_rows($selectClass) > 0) {
// Fetch and do other stuff
$classrow = mysql_fetch_array($selectClass);
$choosedClass = $classrow['classId'];
// etc...
// etc...
}
else {
// Do whatever you need to do if no rows return
}

Categories