I'm developing a login/register form for my client. Right now I am working on the registration part of the form however I seem to have encountered an issue.
I am trying to append the user's input to a database if it does not currently exist. I'm developing this functionality using PHP version 7. However, the code does not seem to append the data to the database even when telling me it has done so successfully.
Here is code:
<?php
if($_SERVER["REQUEST_METHOD"] == "POST") {
//define variables and set values to null
$email = $code = "";
//set variable values to HTML input
$email = $_POST['email'];
$code = $_POST['code'];
//check if email exists
$stmt = $conn->prepare("SELECT userEmail FROM userDetails WHERE userEmail=?");
$stmt->bind_param("s", $prepemail);
//set parameters and execute
$prepemail = $email;
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
echo "email exists";
return false;
} else {
//$stmt->close(); removed as per #Akintunde-Rotimi's suggestion
//insert email into database
$stmt = $conn->prepare("INSERT INTO userDetails (userEmail) VALUES (?)");
$stmt->bind_param("s", $newemail);
//set parameters and execute
$newemail = $email;
$stmt->execute();
echo "New records created successfully";
}
}
?>
The code successfully connects to the database and even tells me if the user already exists. It just doesn't add the user's email to the database and I can't seem to figure out why.
I have researched methods on how to insert the data into the database using prepared statements as I have done here. I've used W3Schools as a reference but still no luck.
The code doesn't seem to have any obvious spelling errors, so have you tried to catch errors? Replace
$stmt->execute();
with
if(!$stmt->execute()) {
trigger_error("there was an error....".$conn->error, E_USER_WARNING);
}
You can also check how many rows are affected, -1 meaning there was an error.
printf("%d Zeile eingefügt.\n", $stmt->affected_rows);
Also, enabling more errors to be shown (at least for development)
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
// ...
Related
PHP login system works on local but doesn't work on Hostgator PHP 7.1. My local is PHP 7.2
I've built out a fully working portal on my local machine. I can CRUD on my local machine. As soon as I put it on the server online, the login system doesn't work. I still can register new users as the user info populates in the DB, so its not a DB config issue. I am getting these errors:
Warning: mysqli_stmt_bind_param(): Number of variables doesn't match number of parameters in prepared statement in .....
Fatal error: Uncaught Error: Call to undefined function mysqli_stmt_get_result() in ....
I have spent 5 hours trying to figure out why it won't work on the Hostgator server but will work on my local.
Here is my code:
if(isset($_POST['loginSubmit'])){
//include connection configs
require '../../db_configs.php';
$email = mysqli_real_escape_string($conn, $_POST['email']);
$password = mysqli_real_escape_string($conn, $_POST['password']);
if(empty($email || $password )){
header("Location: ../../../portalSignIn.php?signin=fieldsempty");
exit();
}
else
{
//user email query
$sqlEmail = "SELECT * FROM users WHERE email='$email'";
$emailResult = mysqli_query($conn, $sqlEmail);
$stmt = mysqli_stmt_init($conn);
//SQL Error
if(!mysqli_stmt_prepare($stmt, $sqlEmail)){
header("Location: ../../../portalSignIn.php?signin=SQL_FAILED");
exit();
}
if(mysqli_num_rows($emailResult) == 0){
//email doesn't exist
header("Location: ../../../portalSignIn.php?signin=incorrectemail");
exit();
}
else
{
//bind data if email exists
mysqli_stmt_bind_param($stmt, "s", $email);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
if($row = mysqli_fetch_assoc($result)){....
Its breaking at this point --> mysqli_stmt_bind_param($stmt, "s", $email);
I've looked into https://www.plus2net.com/php_tutorial/mysqli_mysqlnd.php and Hostagtor doesn't have these settings. And I have used mysqli_stmt_bind_param() successfully on the sign up page.
You have plenty of mistakes in your code. Let me explain a few of them to you.
Don't escape your variables using mysqli_real_escape_string(). Just don't use this function at all.
empty($email || $password ) is going to check a boolean value. This does not make much sense. Remove the empty call and check the negation. If neither $email nor $password then one of them is empty.
Don't use mysqli_query. You are going to prepare a statement, so do not call this function. Also you need to parameterized the SQL. Use ? as placeholder for the value.
mysqli_num_rows in this place would throw an error. You don't need this function at all. If you wanted to use it you would need to pass the as a parameter the output of get_result()
To fetch values using prepared statement you need to prepare/bind/execute/get_result. Only then you can fetch a row if it exists. If nothing is returned then $record will be null.
if (isset($_POST['loginSubmit'])) {
//include connection configs
require '../../db_configs.php';
$email = $_POST['email'];
$password = $_POST['password'];
if (!$email || !$password) {
header("Location: ../../../portalSignIn.php?signin=fieldsempty");
exit();
} else {
//user email query
$sqlEmail = "SELECT * FROM users WHERE email=?";
$stmt = $con->prepare($sqlEmail);
$stmt->bind_param('s', $email);
$stmt->execute();
$result = $stmt->get_result();
$record = $result->fetch_assoc();
if (!$record) {
//email doesn't exist
header("Location: ../../../portalSignIn.php?signin=incorrectemail");
exit();
} else {
// handle your data here
}
}
}
And as always don't forget to enable mysqli error reporting. See How to get the error message in MySQLi?
The issue I am having is because Hostgator does not have mysqlnd available for shared hosting users but only those with VPS or dedicated servers:
https://www.hostgator.com/help/article/compatible-technologies
It can be enabled for other users and instructions can be done following this tutorial:
https://www.plus2net.com/php_tutorial/mysqli_mysqlnd.php
This was a learning lesson, especially in getting to know your webhost.
I have a php script who ask my database with PDO to verify if some values sent exists. If they exists, the database respond with the id of this line's value.
I tested the query on mysql and it works but the value received is false.
This code is only for personal use.
There is the code :
<?php
include("../template/pdo.php");
$query = $pdo->prepare("SELECT id_utilisateur FROM utilisateur
WHERE `mail` IN ( ':mail' )
AND `mdp` IN ( ':mdp' )");
$query->bindParam(':mail', $_GET['identifiant'], PDO::PARAM_STR);
$query->bindParam(':mdp', $_GET['mdp'], PDO::PARAM_STR);
$success = $query->execute();
if($success)
{
$result = $query->fetch();
var_dump($result); //bool(false) actually
if($result == false){
$message = "Try again.";
}
else{
$message = "Congratulation !";
}
}
I tested everything I know :
$_GET is a print/paste from my database table to my url and i have print him
Printed/pasted on phpMyAdmin the query from PDOStatement::debugDumpParams() with my $_GET values
pdo.php work and used on other scripts
No log in my logs files.
Someone can help me ?
Thanks !
If you are testing against a single value use =, not IN.
If you have a list of values, several changes are needed.
The bind code will add quotes, you already have quotes. Remove your quotes.
The basic control structure I'm trying to get to work is to query the DB with the username and email, both of which are unique keys, and if either are in the DB let the user know that they have been taken and to please pick something else. The problem I'm running into is getting the result data in a usable form that I can then check the user-supplied data against.
I cut out the prepared statements for insertion from the snippit, as well as the validation routines, since both of them are working fine.
DB connection snippit
try {
if(!($dbc = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME))){ // Creates the $dbc variable object so we can
// have a connection to the database.
// uses mysqli functions.
throw new Exception;
}
}
catch (Exception $e) {
echo '<p>Could not connect to the database. Please contact the system administrator.</p>';
}
Snippit of Registration script
//before this was validation routines, if anything was wrong the script generated something into $reg_errors which is an array.
if(empty($reg_errors))
{
//queries database if there are any matches for username or email from user input.
if($stmt = $dbc->prepare("SELECT `email`, `username` FROM `users` WHERE `email` = ? OR `username` = ?"))
{
$stmt->bind_param("ss", $e, $u);
$stmt->execute();
$stmt->store_result();
$rows = $stmt->num_rows; //gives the number of rows returned from SELECT query. 0 means no dupes, 1 means one record has BOTH email and username, 2 means two different records (one with email, one with username)
##THIS IS WHERE I'M RUNNING INTO TROUBLE GETTING THE DATA IN A USABLE FORM##
$stmt->close();
} else {
echo "<p>Can't talk to database right now. Try again later, please.</p>";
}
if($rows==0) //no dupes of username or email, so let's try and add them into the DB
{
//prepared statement for insertion into DB
//also get's the count of affected rows. 1 means record inserted correctly.
//asks DB if a new row was created, and if so, thanks user for
//registration on the site & sends an email to their email.
//if query doesnt work, an error is triggered
if($count==1) {
//constructs a thank you note and emails it to the user, using the email they supplied.
exit();
} else {
echo "<p>Unable to process your registration at this time. Please try again later..</p>";
}
} else { // both username and email might be already used in DB, and error msgs are generated for array.
if($rows==2) { // this checks to make sure both entries are dupes
$reg_errors['email'] = 'This email address has already been registered. If you have forgotten your password, use the link to the right to have your password sent to you.';
$reg_errors['username'] = 'This username has already been registered. Please try another.';
} else { //this checks to see which of the two (email or username) is already in DB if both arent dupes.
if((__NEED SOMETHING HERE FROM DB QUERY___ == $_POST['email']) && (__NEED SOMETHING HERE FROM DB QUERY___ == $_POST['username'])) { //both match entries in DB
$reg_errors['email'] = 'This email address has already been registered. If you have forgotten your password, use the link to the right to have your password sent to you.';
$reg_errors['username'] = 'This username has already been registered with this email address. If you have forgotten your password, use the link to the right to have your password sent to you.';
} elseif(__NEED SOMETHING HERE FROM DB QUERY___==$_POST['email']) { // email match
$reg_errors['email'] = 'This email address has already been registered. If you have forgotten your password, use the link to the right to have your password sent to you.';
} elseif(__NEED SOMETHING HERE FROM DB QUERY___==$_POST['username']) { // username match
$reg_errors['username'] = 'This username has already been registered. Please try another one.';
}
} // end of $rows==2 ELSE
} // end of $rows == 0 IF
} else { // end of empty reg_errors conditional
//do something if the reg_error array isnt empty..
}
i'm pretty sure the answer lies in iterations and using meta_data from the result mysqli object, but after beating my head against a wall for a couple days and pouring over the mysqli php manual pages like a maniac, I'm still no closer to figuring out what I should be doing. Could anyone point me in the correct direction?
Starting from the registration script, have you tried this:
if($stmt = $dbc->prepare("SELECT `email`, `username` FROM `users` WHERE `email` = ? OR `username` = ?"))
{
$stmt->bind_param("ss", $e, $u);
$stmt->execute();
$stmt->bind_result($email, $username);
$rows = $stmt->num_rows;
//Move Conditionals Up a Little
if( $rows == 0 ) { //If No Records are Found
//Continue Registration
}
else if( $rows == 1 ) { //If One Record is Found
$stmt->fetch();
//Do Something With $email and $username from DB Here
}
else { //If More than One Record is Found
while( $stmt->fetch() ) { //Iterate Through Records
//Do Something With $email and $username from DB Here
}
}
}
I'm new to PHP and made a simple php site that allows me to submit a form and delete data stored in a database. I was told it was better to use prepared statements to avoid SQL Injection.
I updated my delete and it still works, not sure if it's totally right:
<?php
include("dbconnect.php");
$getid = $_GET["id"];
$delete = mysqli_prepare($database,"DELETE FROM contacts WHERE id IN ($getid)");
mysqli_stmt_execute($delete);
header("Location:http://localhost/address-book");
exit;
?>
But I can't seem to get the add to database feature to work. I tried a variety of different ways to write it, but I'm sure that I'm missing something simple. Here's the unsafe code that I originally wrote:
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
include("inc/dbconnect.php");
// assigns form data to table columns
$assign = "INSERT INTO contacts(firstName,lastName,email,phone,birthday) VALUES ('$_POST[firstName]','$_POST[lastName]','$_POST[email]','$_POST[phone]','$_POST[birthday]')";
//execute query
if (mysqli_query($database,$assign)) {
header("Location:http://localhost/address-book/");
exit;
} else {
exit;
}
?>
If someone could guide me in the right direction I'd be thankful. I'm new to all of this.
UPDATED: I've updated my original code and came up with this instead for delete:
<?php
include("dbconnect.php");
$getid = $_GET["id"];
$delete = mysqli_prepare($database,"DELETE FROM contacts WHERE id IN (?)");
mysqli_stmt_bind_param($delete, 's', $getid);
mysqli_stmt_execute($delete);
header("Location:http://localhost/address-book");
exit;
?>
and the add feature:
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
include("inc/dbconnect.php");
$firstName = "$_POST[firstName]";
$lastName = "$_POST[lastName]";
$email = "$_POST[email]";
$phone = "$_POST[phone]";
// assigns form data to table columns
$assign = mysqli_prepare($database,"INSERT INTO contacts(firstName,lastName,email,phone) VALUES (?,?,?,?)");
mysqli_stmt_bind_param($assign, 'ssss', $firstName, $lastName, $email, $phone);
mysqli_stmt_execute($assign);
exit;
}
?>
A simple Prepare statement is something along the lines of
$query = $this->db->prepare("Query here WHERE something = ?") - note this example is taken from my site so you'll likely have something else instead of $this->->prepare.
The key thing is that the "= something " is denoted as a question mark.
You then bind the value of that question mark to the query
$query->bindValue(1, passed in parameter)
As a fully working example:
//function to add 1 to downloads each time a file is downloaded
public function addToDownload($filename){
$query = $this->db->prepare('UPDATE trainingMaterial SET downloads = downloads + 1 WHERE filename = ?');
$query->bindValue(1, $filename);
try{
$query->execute();
}catch(PDOException $e){
die($e->getMessage());
}
}
Your query `$assign = "INSERT INTO contacts(firstName,lastName,email,phone,birthday) VALUES ('$_POST[firstName]','$_POST[lastName]','$_POST[email]','$_POST[phone]','$_POST[birthday]')";
would be
$assign = "INSERT INTO contacts(firstName,lastName,email,phone,birthday) VALUES ?,?,?,?,?)";
$assign->bindValue(1, '$_POST[firstName]')
$assign->bindValue(2, '$_POST[lastName]')
etc etc
i have this code but i got two errors. I put in the comments the errors
if(!empty($_POST['email']) && validateEmail($email)) {
$email = $_POST["email"];
if ($sql = $db->prepare("select email from users where email=?")) {
$sql->bind_param('s', $email);
$sql->execute();
$sql->bind_result($email);
while ($sql->fetch()) {
$salt = "PiuwrO1#O0rl#+luH1!froe*l?8oEb!iu)_1Xaspi*(sw(^&.laBr~u3i!c?es-l651";
$password = md5($salt . $userExists["email"]);
$pwrurl = "www.yoursite.com/reset_password.php?q=" . $password;
$mailbody = "Dear user,<br><br>If this e-mail does not apply to you please ignore it. It appears that you have requested a password reset at our website www.yoursitehere.com<br>
To reset your password, please click the link below. If you cannot click it, please paste it into your web browser's address bar.<br> <a href='$pwrurl'>$pwrurl</a> <br> <br>
Thanks,\nThe Administration";
$mail->MsgHTML($mailbody);
$mail->AddAddress("dxxb#hotmail.com","Nome da Pessoa");
$mail->IsHTML(true);
if(!$mail->Send()) {
echo "Deu erro: " . $mail->ErrorInfo;
} else {
echo "Enviado com sucesso";
}
}
$sql->close();
$db->close();
}
($sql = $db->prepare('insert into password_reset (code) values (?)')); // Warning: mysqli::prepare() [mysqli.prepare]: Couldn't fetch mysqli in
$sql->bind_param('s', $password); // Fatal error: Call to a member function bind_param() on a non-object
$sql->execute();
$sql->fetch();
$sql->close();
$db->close();
}
all code works fine, but now i need to insert the salt in the db but i can't, and i don't know why
thanks
Edited code to the last version
After you execute a query, fetch returns one result. There may be more -- there may be many, many more -- so you should be calling fetch in a loop to get them all. You aren't supposed to prepare a new query until you've finished dealing with the old one, which would usually mean fetching every row of the result and closeing (in your case) $sql. Otherwise, the database is still in the middle of answering one request when you're trying to issue another one.
The first error says it all - you can't have more than 1 prepared statement/query "in flight" at once. You've not finished fetching data from the first query (select email ...) when you tried to prepare another statement (insert into ...).