I have three queries on my login script. One select query checks the users' credentials, another to update the last login, and the third one is a select query to see whether the user exists in another table, so if the user exists in the table, go some where. If the user doesn't exist, go somewhere else.
The third query is the one is acting weird. Below:
require_once '../includes/sessions.php';
//echo 'hello';
$employerlogindata = $_POST['employerlogindata'];
$data = json_decode($employerlogindata);
$employeremailfromjs = $data->employeremail;
$employerpasswordfromjs = $data->employerpassword;
//sanitization
$employeremail = htmlentities($employeremailfromjs);
$employerpassword = htmlentities($employerpasswordfromjs);
//PHP validation rules
$validflag = true;
function checkblanks($variable){
if($variable == ''){
$validflag = false;
print_r('Empty Inputs. Please try again.');
}else {
$variable = trim($variable);
$variable = stripslashes($variable);
return $variable;
}
}
checkblanks($employeremail);
checkblanks($employerpassword);
if($validflag == false) {
echo 'You have problematic entries. Try again.';
} else {
try{
$sql = "SELECT EID AS dbeid, EMPLOYER_EMAIL AS dbemail, `PASSWORD` AS dbpwd, EMPLOYER_NAME AS dbcompanyname, LAST_LOGIN AS dblastlogin FROM userpwd WHERE EMPLOYER_EMAIL = :employeremail;";
$query = $conn->prepare($sql);
$query->bindParam(":employeremail", $employeremail);
$query->execute();
//echo "select statement successfully executed";
//echo $sql;
} catch(PDOException $e){
echo "Error connecting to server: " . $e->getMessage();
die;
}
//echo $query->rowCount();
if ($query->rowCount() == 0){
echo "Email/Password combo was not found in the system.";
}else {
$result = $query->fetch(PDO::FETCH_OBJ);
//print_r($result);
$dbeid = $result->dbeid;
$dbemail = $result->dbemail;
$dbpwd = $result->dbpwd;
$dbcompanyname = $result->dbcompanyname;
$dblastlogin = $result->dblastlogin;
//echo $dbeid;
if(password_verify($employerpassword, $dbpwd)){
try{
$sql = "UPDATE userpwd SET LAST_LOGIN = NOW() WHERE EMPLOYER_EMAIL = :employeremail; ";
$query = $conn->prepare($sql);
$query->bindParam(":employeremail", $employeremail);
$query->execute();
}catch (PDOException $e){
echo "Error connecting to server: " . $e->getMessage();
die;
}
$_SESSION['EID'] = $dbeid;
$_SESSION['EMPLOYER_EMAIL'] = $dbemail;
$_SESSION['EMPLOYER_NAME'] = $dbcompanyname;
$_SESSION['LAST_LOGIN'] = $dblastlogin;
//echo "Logged in";
} else {
echo "Email/Password combination is invalid. Please Try Again.";
}
try{
$select = "SELECT EID from e_profile WHERE EID=:eid";
$stmt = $conn->prepare($select);
$stmt->bindParam(":eid", $sessemployerid);
$stmt->execute();
}catch(PDOException $e){
echo "Error connecting to server: " . $e->getMessage();
die;
}
$res = $stmt->fetch();
$eid = $res['EID'];
$count = $stmt->rowCount();
if($stmt->rowCount() == 1){
echo "employerdashboard.php $eid $count";
$stmt->closeCursor();
} else if ($stmt->rowCount() == 0){
echo "e_profile.php $eid $count";
$stmt->closeCursor();
}
}
}
?>
After a set of login credential is successful, the script hits both the second and the third queries. However, the third query takes on the results of the previous ran query. After a second click on the frontend with the same credentials, it produces the right results.
I thought maybe I could find the functionality of mysqli_free_result() in PDO's closeCursor, but that doesn't work. I want it to produce the right result the first time.
Any clues as to why this is happening?
Your variable is out of date (or at least that is my theory), as I said in the comments.
If you have
global $sessemployerid = $_SESSION['EID'];
Then you do
$_SESSION['EID'] = $dbeid;
Then you use $sessemployerid it will not be equal to $_SESSION['EID'] = $dbeid. It will be equal to the previous value of the session when it was assigned, which may or may not be correct. Probably on the first attempt it is wrong, then on subsequent attempts it is correct.
Just to lay it out a bit further:
//you assign $sessemployerid way up here
global $sessemployerid = $_SESSION['EID'];
...
//then you update the session
if(password_verify($employerpassword, $dbpwd)){
try{
$sql = "UPDATE userpwd SET LAST_LOGIN = NOW() WHERE EMPLOYER_EMAIL = :employeremail; ";
$query = $conn->prepare($sql);
$query->bindParam(":employeremail", $employeremail);
$query->execute();
}catch (PDOException $e){
echo "Error connecting to server: " . $e->getMessage();
die;
}
$_SESSION['EID'] = $dbeid; //<--- here you update the session but neglect $sessemployerid
$_SESSION['EMPLOYER_EMAIL'] = $dbemail;
$_SESSION['EMPLOYER_NAME'] = $dbcompanyname;
$_SESSION['LAST_LOGIN'] = $dblastlogin;
//echo "Logged in";
} else {
....
//then you use $sessemployerid, but it has a stale value (sometimes)
$select = "SELECT EID from e_profile WHERE EID=:eid";
$stmt = $conn->prepare($select);
$stmt->bindParam(":eid", $sessemployerid);
To fix this you could use a reference assignment
global $sessemployerid =& $_SESSION['EID'];
This can be demonstrated by this simple code:
$a = 1;
$b =& $a; //initial assignment, with reference
echo $b."\n";
$a = 2; //change the value of $a
echo $b; //$b is auto-magically updated
See it here
Ouputs
1
2
If you do it this way (the "normal" way)
$a = 1;
$b = $a; //initial assignment, normal
echo $b."\n";
$a = 2; //change the value of $a
echo $b; //$b is not updated
The output is
1
1
Alternatively you could simply update the global after changing the session's value:
if(password_verify($employerpassword, $dbpwd)){
...
$_SESSION['LAST_LOGIN'] = $dblastlogin;
global $sessemployerid = $_SESSION['EID'];
}else{
...
Because the value of $sessemployerid is out of sync with $_SESSION['EID'] you will get inconstant behavior depending on if you had updated the session or not on a previous page attempt.
Hope that makes sense.
Related
I'm making a function that i have to check if a userid is in this table already: if not he has to get into another page yet. But for some reason I get "NULL" back instead of the number of the userID.
my class:
public function countHobbies($userID){
try{
$conn = Db::getConnection();
$statement = $conn->prepare("select * from hobby where userID = '".$userID."'");
$userID = $this->getUserID();
$statement->execute();
$aantal = $statement->fetchAll(PDO::FETCH_ASSOC); //
$aantal->execute();
}
catch(throwable $e){
$error = "Something went wrong";
}
}
and this is on my html page:
$userArray = $_SESSION['user_id'];
$userID = implode(" ", $userArray);
$hobby = new Hobby();
$count = $hobby->countHobbies($userID);
if($count == false){
echo "no";
//header('Location: hobby.php');
}
else{
echo "yes";
}
There are at least two things you need to fix:
Always use parameter binding on the SQL statement. It may not be a security problem in this particular instance, but do get into the habit of using prepared statements. Because otherwise you'll find yourself in situations where you should've but didn't. https://www.php.net/manual/en/security.database.sql-injection.php
The $userID variable must be assigned before it is used.
In the end, it could look like this:
$userID = $this->getUserID();
$statement = $conn->prepare("select * from hobby where userID = ?");
$statement->bind_param("s", $userID);
can you help out a beginner trying to learn PHP? I wrote a code for changing password without any validations yet, just to change it and it does not work. It's been days I've been trying and couldn't figure out what's wrong. Thanks in advance.
id is variable name in database where id is kept.
db connection is done with first line and it definitely works.
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
session_start();
print_r($_SESSION);
function changePSW()
{
//$password = $_POST['currPassword']; // required
$newPassword = $_POST['newPassword']; // required
//$newPassword2 = $_POST['NewPassword2']; // required
$newPasswordH = password_hash($newPassword, PASSWORD_DEFAULT);
echo($newPassword);
$id = $_SESSION['userID'];
echo($id);
// create PDO connection object
$dbConn = new DatabaseConnection();
$pdo = $dbConn->getConnection();
try {
$statement = $pdo->prepare("SELECT * FROM `users` WHERE id = :id LIMIT 1");
$statement->bindParam(':id', $id);
$statement->execute();
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
echo "SADASDASD";
// no user matching the email
if (empty($result)) {
$_SESSION['error_message'] = 'Couldnt find user';
header('Location: /Online-store/userForm.php');
return;
}
$sql = "UPDATE users SET password=:newPasswordH WHERE id = :id";
// Prepare statement
$stmt = $pdo->prepare($sql);
echo "AFGHANIKO";
// execute the query
$update_status = $stmt->execute(array(':password' => $newPasswordH, ':id' => $id));
echo "IHAAA";
echo($update_status);
if ($update_status === TRUE) {
echo("Record updated successfully" . "\r\n");
echo nl2br("\nPassword: ");
echo ($newPassword);
echo nl2br("\nHashed Password: ");
echo ($newPasswordH);
return true;
} else {
echo "Error updating record";
die();
}
} catch (PDOException $e) {
// usually this error is logged in application log and we should return an error message that's meaninful to user
return $e->getMessage();
}
}
if($_SESSION['isLoggedIn'] == true) {
require_once("database/DatabaseConnection.php");
unset($_SESSION['success_message']);
unset($_SESSION['error_message']);
changePSW();
}
?>
$update_status = $stmt->execute(array(':newPasswordH' => $newPasswordH, ':id' => $id));
This is what I needed to have instead of
$update_status = $stmt->execute(array(':password' => $newPasswordH, ':id' => $id));
So I am grabbing the amount of rows in a specific table where the username is already in the database like so:
$second_sql = $db->prepare("SELECT * FROM users WHERE username = :username");
$second_sql->bindParam(':username', $username);
$second_sql->execute();
if($second_sql->rowCount() == 1) {
$db = null;
header("Location: ../login/");
} else {
$statement->execute();
$db = null;
}
The problem is it's not working. If you need more of the script just tell me.
Some databases does not report the row count with PDO->rowCount() method.
SQLite, for instance.
So don't use rowCount(); doing so makes your code less portable.
Instead use the COUNT(*) function in your query, and store the result in a variable.
Finally, use that variable to fetch the one and only column (users) using the fetchColumn() method.
So you can play with this:
try {
$second_sql = $db->prepare("SELECT COUNT(*) from users WHERE username = :username");
$second_sql->bindParam(':username', $username, PDO::PARAM_STR);
$second_sql->execute();
$count = $second_sql->fetchColumn();
} catch (PDOException $e) {
// Here you can log your error
// or send an email
// Never echo this exception on production
// Only on development fase
echo "Error: " . $e->getMessage();
}
if ($count) {
$db = null;
header("Location: ../login/");
} else {
$statement->execute();
$db = null;
}
Perhaps you wanna test you condition for a single row:
if ($count == 1)
Hope this helps you.
Cheers!
What i'm trying to do is make a function that gets a user permission level as seen here.
function userPermission($level, $conn){
try{
$sql = "SELECT * FROM `users` WHERE username = :Player AND level = :Level ";
$s = $conn->prepare($sql);
$s->bindValue(":Player", $_SESSION['username']);
$s->bindValue(":Level", $level);
$s->execute();
return true;
} catch(PDOException $e) {
error_log("PDOException: " . $e->getMessage());
return false;
}
}
and once I go to the page and input the code that should in-tile the functionality of this function. It doesn't work at all.
Here is the code that I inputted
<?php if (!userPermission('0', $conn) == 2) {
echo '<input type="radio" id="tab-7" name="tab-group-1">
<label for="tab-7">Permissions</label>';
} else {
echo '<input disabled=disabled type="radio" id="tab-7" name="tab-group-1">
<label id="disabled" for="tab-7">Permissions</label>';
}
?>
The 0 is the current level of the user and I was using that as a test, as for the == 3 that's what the rank has to be in order to access the tab
Anyways, I'm either doing this wrong or I don't know what i'm doing. I get no errors at all but the code I inputted seems unreliable.
Your code just execute but does not return the query result.
I modified your code a little bit as an example
function userPermission($username,$level, $conn){
try{
$sql = "SELECT `user_permission`
FROM `users`
WHERE username = :username AND level = :Level ";
$s = $conn->prepare($sql);
$s->bindValue(":username", $username);
$s->bindValue(":level", $level);
$s->execute();
$row = $s->fetch();
return $row['user_permission'];
} catch(PDOException $e) {
error_log("PDOException: " . $e->getMessage());
return -1;
}
}
Make sure the session is set also
session_start();
$usermame = $_SESSION['username'];
if (!userPermission($username,'0', $conn) == 2) {...
the fragment code
if (!empty($_POST)) {
$query = "SELECT userid FROM user WHERE email = :email";
$query_params = array(':email' => $_POST['email']);
try {
$stmt = $db->prepare($query);
$result = $stmt->execute($query_params);
}
catch (PDOException $ex) {
$response["success"] = 0;
$response["message"] = "Database Error Get User ID!";
die(json_encode($response));
}
if ( false !== ($user = $stmt->fetch()))
{
$userid = $user['userid'];
}
else {
$response["success"] = 0;
$response["message"] = "Why you come here!";
die(json_encode($response));
}
I want to ask is that after that $row = $stmt->fetchAll(); How should I write the code of assigning the userid into $userid And php doesn't save the row result into a variable.
fetchAll() returns an array. so $row['userid'] will not be set. $row[0]['userid'] will.
Betterh would be to use:
if ( false !== ($user = $stmt->fetch()) )
{
$userid = $user['userid'];
} else
{
//user not found
}
What this code does, it tries to fetch a row fromt the statement. IF no row was found ->fetch() returns a boolean false. As long as it doesn't return false, we have a row from the statement that is available in the $user var now :)
$userID = isset($row['userid']);
Simply checks if $row['userid'] is set, i.e. it's a bool value.
Simply checking whether the array is empty or not will be sufficient for you to fetch the value straight away:
if(!empty($row))
{
$userId = $row['userid'];
}
You need to make your question become more precise, if this isn't what you're asking for.