PHP always reports SQL success even when it fails - php

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 />';
}
}

Related

Need to select specific row and a specific column within that row and compare it with a php variable

This is my block of code for doing that. It works fine until it reaches the last if statement. I cannot get it to find the Graphics column using the Department_ID. I am trying to check if the user input is equal to a id within the table. Then check if that id requires graphic work done. To do that, I need to find out that for that specific project graphic is a 1 in the database.
if($graphics_id != Null)
{
$query = mysqli_query($connect,"SELECT * FROM Project_Overview WHERE Project_ID='".$graphics_id."'");
$row = mysqli_fetch_assoc($query);
//echo $row['Project_ID'];
if($graphics_id == $row['Project_ID']) //if the graphics_id matches a project_id in the table
{
$result = mysqli_query($connect, "SELECT Graphics FROM Department WHERE Department_ID ='".$graphics_id."'")
$row = mysqli_fetch_assoc($result);
if($result)
{
echo $row['Department_ID'];
} else {
echo "This Project does not require graphics!"
}
} else {
echo "Project_ID ".$graphics_id." does not exist!";
}
}
A few thoughts:
The second SELECT Statement selects the Graphics column, but later you are echoing $row['Department_ID']; which should be empty as the only key in $row would be Graphics
The last if-Statement is if($result). Don't you mean if($row)? If $result is false (and hence "This Project does not require graphics!" is printed out), this would indicate, that mysqli_query has failed, possibly because of an error in your second SQL statement.
And, as ThomasEllis said, a JOIN would be nicer and SELECT * is not wrong but returns (probably) more than you need.
Depending on where $graphics_id comes from (a user input?) you should consider escaping it for security reasons ($graphics_id_escaped = mysqli_real_escape_string($connect, $graphics_id); - just in case ;)

PHP MySQL Check for Key then implement if not used

I am trying to check my database for a key that has already been put in. If the key exists then I need it to check to make sure the username field hasn't been filled. If it has then it needs to throw an error so that it doesn't update and overwrite the information already stored in the database.
Everything works. The update functions etc. the only part that does not work is the checking if the key exists and if the username portion is filled(not sure exactly how to do that) before updating the database.
Thanks,
Cameron Andrews
Code:
// If the Register form has been submitted
$err = array();
if(strlen($_POST['username'])<4 || strlen($_POST['username'])>32){
$err[]='Your username must be between 3 and 32 characters!';
}
if(preg_match('/[^a-z0-9 _]+/i',$_POST['username'])){
$err[]='Your username contains invalid characters!';
}
if(!checkEmail($_POST['email'])){
$err[]='Your email is not valid!';
}
$resultN = mysql_query("SELECT * FROM Users WHERE key='".$_POST['kgen']."'");
while($row = mysql_fetch_array($resultN))//for the results that are returned set the local variables
{
if($_POST['kgen'] == $row['key']){
if($_POST['username'] == $row['usr']){
$err[]='Username already in use';
}
}else if($_POST['kgen'] == ""){
$err[]='Invalid Key Code!';
}else{
$err[]='Error occured please try again';
}
}
if(!count($err)){
// If there are no errors
$_POST['email'] = mysql_real_escape_string($_POST['email']);
$_POST['username'] = mysql_real_escape_string($_POST['username']);
$_POST['pass'] = mysql_real_escape_string($_POST['pass']);
// Escape the input data
$theName = $_POST['name'];
$theUser = $_POST['username'];
$thePass = $_POST['pass'];
$theEmail = $_POST['email'];
$theType = "member";
$theRegIP = $_SERVER['REMOTE_ADDR'];
$theDate = "NOW()";
$theKey = $_POST['kgen'];
// If everything is OK register
mysql_query("UPDATE cad.Users SET name = '$theName', usr = '$theUser', pass = '$thePass', email = '$theEmail', type = '$theType', regIP = '$theRegIP', dt = '$theDate' WHERE Users.key = '$theKey'");
Here is how I would approach it:
I would use mysqli or PDO instead of deprecated mysql functions.
I would rewrite all the queries to use prepared statements instead of concatenating your query string together - you have significant SQL injection vulnerability now.
But, since I am not going to rewrite your entire section of code for you, the rest of my approach will be described based on your current mysql/concatenated-query-string approach.
I would put a unique index on name field, but allow NULL value on the field.
I would simply run an update query rather than trying to run an unnecessary select plus an update.
UPDATE cad.Users
SET
name = '$theName',
usr = '$theUser',
pass = '$thePass',
email = '$theEmail',
type = '$theType',
regIP = '$theRegIP',
dt = NOW() /* don't pass 'NOW()' in single quotes as you are currently doing */
WHERE
Users.key = '$theKey'
AND User.name IS NULL;
If you get an error here you should look at error messaging to determine if update failed due to a unique constraint violation (user tried to enter a name that was already used in another record associated with a different key), or some other unexpected reason.
Assuming there was no error, I would then call mysql_affected_rows() (or appropriate equivalent in mysqli or PDO). If the return value is 1, an update was made. If the return value is 0, then no update was made because you did not have any rows that satisfied the WHERE condition.
If you get 0 affected rows, you can re-query the database if you really want to determine if the cause was no matching key or an existing user name.
SELECT name FROM Users WHERE key = '$theKey';
If you get no rows in the result it is because the key is missing, otherwise it is because the name was not a NULL value.
The net is that in the happy path use case, you only make a single query against the database rather than two, with two queries only being necessary if you want to determine the reason no update occurred for those cases. Your current approach always requires 2 queries.
First of all, you should see this. At second, i see, you have strange logic. Try to simplify it. :) As for me, i think it should looks like this:
<?php
if (strlen($_POST['username']) < 4 || strlen($_POST['username']) > 32) {
throw new RuntimeException('Your username must be between 3 and 32 characters!');
} elseif (preg_match('/[^a-z0-9 _]+/i', $_POST['username'])) {
throw new RuntimeException('Your username contains invalid characters!');
} elseif(!checkEmail($_POST['email'])) {
throw new RuntimeException('Your email is not valid!');
} elseif (empty($_POST['kgen'])) {
throw new RuntimeException('Invalid Key Code!');
}
$resultN = mysql_query("SELECT * FROM Users WHERE `key`='{$_POST['kgen']}' AND `usr`='{$_POST['username']}';");
$user = mysql_fetch_array($resultN);
if (!empty($user)) {
throw new RuntimeException('Username already in use');
}
// if all is fine - update
You can use exceptions for checking error. Benefit - you don't go to next check, if failed prev. You also have ability to show user exception message or reason(better use custom exception for this). Negative - you can't get list of errors.

Checking for non-null (or null) result set for Firebird with PHP5

So, I haven't used firebird for that long, but i'm writing a search engine for a database we have. There is a field that required you to ask for a reason the record was changed if you edit the record for some reason. If the user fails to input this reason, I mark it in another table, to keep track of it all.
So, in my search results, I query this second table, and I'm trying to check for a non null (no one entered a reason for change) result set. However, I've tried using both ibase_query and ibase_fetch_row return results, and it doesn't work as expected.
I've been going off of the php manual, and it says they should return TRUE (for ibase_query) or FALSE (for ibase_fetch_row) if the result set has nothing.
http://php.net/manual/en/function.ibase-query.php
http://php.net/manual/en/function.ibase-fetch-row.php
Here is the code for the ibase_fetch_row:
$query3 = "Select CHANGE_REASON from REASON_FOR_CHANGES where id = $id";
$result3 = ibase_query($link, $query3);
if (ibase_fetch_row($result3) != FALSE) {
$reasonChange = "<span style='color:red'>".
"No Reason Given. <a href='changeReason.php?id=$id'>Add Reason</a></span>";
}
And for ibase_query:
$query3 = "Select CHANGE_REASON from REASON_FOR_CHANGES where id = $id";
$result3 = ibase_query($link, $query3);
if ($result3 == TRUE) {
$reasonChange = "<span style='color:red'>".
"No Reason Given. <a href='changeReason.php?id=$id'>Add Reason</a></span>";
}
Anyone have any clue what I'm doing wrong? It seems like the returns from the two functions aren't as documented.

PHP mysql_affected_rows() Should I Care?

I have always struggled with a fairly basic concept in my PHP INSERT/UPDATE code. Should I always be checking for the number of affected rows after every INSERT/UPDATE because in the vast majority of times I am only ever performing one INSERT/UPDATE and it seems to cause more problems than it fixes by checking that only one row was affected.
Below is my standard code to perform the INSERT/UPDATE and this code fails if the user is updating a record without changing anything because the affected rows will be 0. I could write code to check that at least one field has changed but on large forms this seems very clunky and was wondering if it is really worth it because I have never really ever caught any errors by checking this number anyway.
<?php
$whereSql = '';
$groupSql = 'INSERT INTO';
if(isset($_POST['id']) && is_numeric($_POST['id'])){
$groupSql = 'UPDATE';
$whereSql = 'WHERE id = ' . $_POST['id'];
}
$groupSql .= ' sometable SET name="' . $name . '" ' . $whereSql;
$groupDb = mysqli_query($groupSql, $dbObject) or die("Login DB error:".mysql_error());
if(mysqli_affected_rows($dbObject) == 1){
//redirect
}else{
die('System Error');
}
You should be checking return values on queries. A select/update query which affects/returns no rows is NOT an error condition, it's simply an empty result set, or an update which happened to affect nothing.
$result = mysql_query($sql) or die(mysql_error());
^^^^^^^^^^^^^^^^^^^^^
Consider a user signup system which checks for the existence of a matching username:
SELECT id FROM users WHERE username='foo';
if the user foo does not exist, your system will barf and claim an error occurred. But an empty result set is NOT an error. It simply means the username is available for user.
Same for a system that handles grades:
UPDATE students SET failed=true WHERE score < 50;
getting 0 affected rows is NOT a failure. It just means all the students passed.
I would recommend checking if the query has failed, and if not, then if there was more than one row affected.
$groupDb = mysql_query($groupSql, $dbObject);
if (false === $groupDb) {
die("Login DB error:".mysql_error())
if (mysql_affected_rows($dbObject) > 1) {
die('System Error: failed to ' . $action . ' a document Group');
} else {
//redirect
}
This way you will redirect only in case of successful queries and if there was less than 2 rows affected (if that is important to you).

Is using mysql_num_rows (rowCount in PDO) necessary in update or insert query?

Should I be using mysql_num_rows (rowCount in PDO) in update or insert query?
Currently, my code looks likes this,
public function update_username(){
$q = "UPDATE usertable SET username = '$user_name' WHERE id = '$user_id' LIMIT 1";
$r = $db->query($q);
if($r){
$message = "Updated successfully";
return $message;
}else{
return false;
}
}
Should I change it to like this?
public function update_username(){
$q = "UPDATE usertable SET username = '$user_name' WHERE id = '$user_id' LIMIT 1";
$r = $db->query($q);
if($r){
$num = $r->rowCount();
if($num == 1){
$message = "Updated successfully";
return $message;
}else{
$message = "An error occurred";
return $message;
}
}else{
return false;
}
}
Normally, query goes through without any error, so I shouldn't worry about it too much, but which one would be a better coding practice? Or do you suggest something else?
Thanks so much in advance!
Actually the two codes do something different.
The first one will print "Update success" if the query was successfully executed. But a query can be successfully executed also without affecting any row, i.e. you have a WHERE statamenet that does not match. The second code will not print "Update success" if no rows were affected.
Of course, if you're sure that your WHERE statement has to match, you can use both codes without any difference and using the second one could help you to spot any potential bug, i.e. it doesn't match and so something went wrong (probably the id was different from the one you expected).
Generally, to answer your question, mysql_num_rows is needed only if you want to know how many lines were affected. It's not mandatory at all to use it.
So, it depends on what you want. Both are good, but they are different.
If you are 100% sure the variables are created by you and not someone else you can do it like that, but you can minimize the code more:
public function update_username(){
$q = "UPDATE usertable SET username = '$user_name' WHERE id = '$user_id'";
if($db->query($q)){
return "Updated successfully";
}
return false;
}
First, because a query is executed successfully, doesn't necessarily mean that anything has been updated. So if you need to distinct the difference between a queries validity or the update change, then yes, rowCount would be a good practice.
Second, a prepared statement would be more wise to use when assigning variables (SQL injection, etc).
public function update_username(){
$q = "UPDATE usertable SET username = :user_name WHERE id = :user_id LIMIT 1";
$r = $db->prepare($q);
$r->bindValue(':user_name', $user_name);
$r->bindValue(':user_id', $user_id);
if($r->execute()){
$message = "Updated successfully: updated ".$r->rowCount();
return $message;
}else{
return false;
}
}
To avoid code duplication, maybe you should consider avoiding writing the same execution code for a query, and move that to a method/function which does that all for you, e.g
public function validateStmt($r) {
// validate query
if($r->execute()) {
// check result set
if($r->rowCount() > 0) {
return $r;
}
else {
// if a result set IS expected, then you might consider to handle this as
// a warning or an error
}
}
else {
// query invalid
}
}
Depending on the situation, you will have to choose which part you should use. mysql_num_rows() is used to check how many rows have been affected from your query you have executed. So, it's up to you to decide whether it is really necessary to add the mysql_num_rows() function in to your code or not.

Categories