Can’t understand PHP/MySQL user registration functionality… - php

First, I’m not a programmer by nature, so I’m having trouble understand what’s happening in the below script (put together from a number of resources for a user registration form):
if (mysqli_query($dbconnect, $sql))
{
header("Location: registered.php");
}
else
{
$_SESSION['error_reg']['email'] = "This email address is already registered.";
}
In this snippet, $dbconnect contains the MySQL connection script (using mysql) and $sql contains the sql table insertion code. Finally, the session info injects an error message into another script that’s under the form.
My question revolves around how the script knows if the email address exists in the table (it works, it really does) without having to select the row from the table. I’ve been seriously scratching my head about how it is work when I haven’t explicitly coded it to do so.
I hope that this isn’t vague enough… There’s really not much more to the script aside from some form field validation and capturing the form variables for insertion into the table (in $sql).
Thanks!

My question revolves around how the script knows if the email address exists in the table
It actually doesn't know in this case. It assumes. This is actually a pretty poor example of that described functionality. This code is assuming that any failure of the database query means that the email address is already registered.
If there is any failure in executing the query (a syntax error, a database engine failure, anything), then mysqli_query($dbconnect, $sql) is going to return false. This code interprets that false value as the specific error message it displays.

It can't possibly work. mysqli_query() has two possible return values: a statement handle/object if the query succeeded, or boolean false if the query outright failed.
A query which returns NO rows (e.g. select .. where 1=0) is NOT a failure. It's a perfectly valid query, which simply happens to have an empty result set.
A proper code sequence would be:
$result = mysqli_query(...) or die(mysqli_error($dbconnct));
if (mysqli_num_rows($result) == 0) {
return "not registered";
} else {
return "already exists";
}

Related

How to handle PDO transaction errors to inform to the client the result of it?

As you know, a transaction is composed of multiple prepared statements that is executed one by one, if one of that statements fails, it will throw a PDOException, you can catch it and get the error message, but this error message is for the "developer", I need to show an specific error to the final user like: "The transaction failed because ....", that '....' is the reason I need to show to the client.
I have an idea to solve this and it is using an array named 'query_trace', that array will put a key for the executed query and a result of that execution like:
// prepare statement, bindParams....
$query_trace['query1_insert_user'] = "OK"
// prepare statement, bindParams....
$query_trace['query2_insert_user_more_information'] = "OK"
// prepare statement, bindParams....
$query_trace['query3_create_user_account'] = "FAILED"
(That FAILED string is stablished in the catch:
} catch (PDOException $e)
{ $query_trace['query3_create_user_account'] = "FAILED" }
return $query_trace; ...
Then in the controller when I get the query_trace response, I will check:
if ($query_trace['query1_insert_user'] != "OK")
echo "The data for the user is not valid";
else
if ($query_trace['query2_insert_user_more_information'] != "OK")
echo "The additional information of the user is not valid";
else
if ($query_trace['query3_create_user_account'] != "OK")
echo "The username is not valid or actually exists";
else
echo "The transaction was great!";
The question is that this is a good way and/or PDO offers some functions/methods to "auto-trace" this?
Thanks.
Judging by error messages, you don't need neither a transaction nor multiple statements.
Just validate the user input before doing any inserts, then insert the user data into a single user talbe, without any transactions.
The only possible case that you would want to report to a user is a duplicate username. In this particular case you may want to catch the error, check whether it's a duplicate key, and if so - report that report to the user. Otherwise just re-throw the exception and let a site-wider error-handler to tell a user that something went wrong.
This makes little sense since a transaction turns a bunch of request to one "atomic" request. So trying to get information about the sub atomic elements is quiet odd.
So I'm not aware of any "easy way" to do so.
You may also do a SELECT before every statement (but it might get tricky if the SELECT is the statement that failed). It would probably work for PROCEDURE too.
SELECT "The user creation failed";
INSERT INTO user (...) VALUES (?,...,?);
SELECT "The user subinfos save failed";
INSERT INTO user_subinfos...;
Note that user will only know which statement failed, not why it failed.

Stop user using email verification link more than once. PDO prepared statement not functioning

EDIT: based on first reply I got below,I reworked my code and it now works... first checking the given email address to find the gamer id. Then checking the verfication state based on the gamer id. So if they change their email address in the future it will still know whether it's already been verified.
Below is my final code, (I've changed some name for items, so its not an exact copy/paste of my own code).
function email_not_verified ($email) { //check it's not already verified
include ('../connect.php'); // Include connect to database functions
$findUser= $db->prepare("SELECT game_id FROM players WHERE email=?");
$findUser->execute(array($email));
$user = $findUser->fetch();
if ( $findUser){
$veri= $db->prepare("SELECT sent_verification FROM players WHERE game_id=?");
$veri->execute(array($user["game_id"]));
$results = $veri->fetch();
$final = $results["sent_verification"];
}
if ($final == 1){
return TRUE;
}
else{
return FALSE;
}
}
Thanks again for the help.
Below, is my original question.
I'm trying to figure out a simple setup that stops a user repeatedly verifying their email address. As when they verify their email I'm awarding them a bonus of 300 credits for in store game purchases. I obviously don't want to keep dishing that out each time they follow their emailed verification link.
So I'm trying to run a check first, before the normal verification script is run.
But surprise, surprise: its not working...
I was trying to search my database for the email address with the verification field set to '1', I'd then see how many times it found this result. If it found it '0' times then that's fine to verify, if it found it once then its already been verified before.
function email_not_verified ($email) {
include ('../connect.php'); // connect to database
//check it's not already verified
$checkEmail= $db->prepare("SELECT * FROM players WHERE sent_verification=?, email=?");
$checkEmail->execute(array('1', $email));
$check2 = $checkEmail->rowCount();
if ($check2 = 1){
return TRUE;
}
else{
return FALSE;
}
}
I've been using
file_put_contents('results.txt',$check2);
to see the results of the code regardless of whether its putting out a TRUE or FALSE. But the result comes back as '0', even though I can see from looking at my database it should be '1'.
I'm not sure if there's a whole easier way to approach this, I keep trying to get my head around bind values but it's not yet sinking in... I'll continue to try.
Thanks for any help, guidance, pointing out the obvious... I feel like I've taken the wrong path with my script but can't think how else to approach it...
Cheers
Jon
Your if statement is wrong. You're using the assignment operator instead of comparison. This doesn't matter though because rowCount isn't always reliable, which is probably where the actual problem is. What you need to do is fetch the first row and see if you get a row back.
However, you probably don't want to attach this to e-mail verification. When users change their e-mail address, you will want to verify that new address and you probably don't want to give them 300 more credits each time they do. Otherwise, someone could programmatically change their e-mail address over and over again, creating a lot of credits for themselves.
I would separate out the 300 free credits as a coupon or something that can only be used once per account. On e-mail verification, if that coupon hasn't already been used up for that account, use it and mark it as such in your database. This could be done simply by adding another column for new_account_bonus_credits or something.

How do I test if my MySQL update query was successful when there is no update in Code Igniter?

I know it is a frequently asked question, but let me explain a bit why I need to ask that again.
Most answers out there suggests using
$this->db->affected_rows()
This is not working in my situation as I may have situation that the update data is the same as the data in the database, so it will return 0 even if the update is success.
I know I can write another query to check if it is because the data are the same, but this sounds stupid to me.
Another way is to use the Active Record Class in code igniter, so the line will be something like:
$error_num = $this->db->update("users", array('firstName' => $newFirstName));
return $error_num;
which is a better solution (at least it works even if there is no update due to repeated data). However, I would like to use the database class, i.e. something like:
$this->db->query('update table set field = somedata where id=1');
It increases the readability of my code to coder who knows php + SQL but are not familiar with code igniter, but then this is why I am asking if anybody knows how do I get the error number if I query in this way?
i.e. Something like mysql_errno() when using mysql_query($query) in PHP.
Both will work like same only difference
if you using active record class all the input variables are escaped automatically
If you want security you better to go with active record class
If you use normal query execution you have to escape the input parameters manually using $this->db->escape_str()
$id = $this->db->escape_str($id)
You can check the query execution status.
$status = $this->db->update("users", array('firstName' => $newFirstName));
if($status)
{
//here you can check the number of affected rows if required
echo $this->db->affected_rows();
}else{
//here you can prcess for failure case
log_message('Error', $this->db->_error_message());
}
//return the status to required place
return $status
I have use this code for checking.
$status = $this->db->query('update table set field = somedata where id=1');
if($status)
return true;
else
return false;

Problem with UPDATE MySQL

I have a bit of an issue with my code.
I'm making an administrative panel for users to add things to the database. On occasion, they might try to save data without changing it (open a dialog, click save without changing anything). This, of course, will make mysql_affected_rows() return '0' when checking to see if the UPDATE query worked.
Is there another query to make that will always UPDATE regardless of whether the data is the same or not (or can I modify a simple UPDATE query to always update)?
EDIT
This is for users who don't have programming experience. Of course you wouldn't want to update if there's no reason to, but when a user tries to update and it doesn't happen I end up showing a failure message. Rather than there being something wrong, its just it doesn't need to be updated. I need a way to show the user that, instead of a generic 'failure' message. If it failed for another reason, I still need to know.
From the MySQL Documentation:
If you set a column to the value it currently has, MySQL notices this
and does not update it.
Instead of checking mysql_affected_rows, just check to see if the query was successful:
if(!mysql_query("UPDATE ..."))
{
//failure
}
else
{
$verification = mysql_query("SELECT ROW_COUNT() as rows_affected");
$row = mysql_fetch_row($verification);
$rows_affected = $row[0];
if ($rows_affected > 0)
{
//update was performed
}
else
{
//no update was needed
}
}

PHP: managing url $_GET tinkering

Here's a situation, i have a list of support tickets that when you click the title of the ticket takes you to a page that displays the ticket in more detail. If uses URL GET variables to query the database. I've taken SQL injection into account but what if someone modifies the url to an id that doesn't exist? whats the best way to deal with that?
Thanks,
Jonesy
If the ID does not exist, send a 404 - Not Found header along with a nice error page telling the user that it wasn't found.
You probably have to make a page handling unsuccessful searches anyway; just route it in there. Then you can help the user to find what (s)he searches in a consistent way, provide cues and "most-searched-after" and what not.
This may seem too simple, but you should always validate your GET (or POST) variable before doing anything with them. In your case, just verify that the ID exists in the database. If it doesn't, inform the user.
You should always check if your query returned anything. If it returned 0 rows, the ID doesn't exist.
<?php
$result = mysql_db_query("your query", $link);
$num_rows = mysql_num_rows($result);
if($num_rows < 1) {
// row with that id doesnt exist
// do whatever you want
} elseif($num_rows > 1) {
// you have problem with your ids in db
} else {
// everything went fine
// do your thing here
}
?>
Check if the ticket exists; if not, react accordingly. What "react accordingly" means is determined by your business logic: create a new ticket? raise an error? take the user to a list of available tickets?
An example using the old mysql extension for brevity:
$sanitized_numeric_id = (int) $_GET['ticket_id']; // assuming id is numeric
$query_resource = mysql_query('SELECT `somecolumn`, `column2`, `othercolumn`
FROM `tickets`
WHERE `id`= ' . $sanitized_numeric_id);
if (mysql_num_rows($query_resource) > 0) {
// the ticket exists, do something with it
} else {
// the ticket doesn't exist, react accordingly
}

Categories