PHP DB connection and password verification - php

I have three errors
Warning: mysqli_stmt::fetch() expects exactly 0 parameters, 1 given in
/Volumes/shared/Digital/_Websites/_TEST/qpm/classes/mysql.php on line
20
Notice: Trying to get property of non-object in
/Volumes/shared/Digital/_Websites/_TEST/qpm/classes/mysql.php on line
23
Notice: Trying to get property of non-object in
/Volumes/shared/Digital/_Websites/_TEST/qpm/classes/mysql.php on line
23
Here is my code
<?php
require_once 'includes/constants.php';
class mysql{
private $conn;
function __construct(){
$this->conn = $conn = new MySQLi(DB_SERVER, DB_USER, DB_PASSWORD, DB_NAME)
or die ('There was an error in the connection');
}
function verify ($un, $pwd){
$username = $un;
$password = $pwd;
if ($sth = $this->conn->prepare("SELECT pass FROM User WHERE username = '".$un."' LIMIT 1")) {
$sth->execute();
$user = $sth->fetch(PDO::FETCH_OBJ);
// Hashing the password with its hash as the salt returns the same hash
if (crypt($password, $user->hash) == $user->hash) {
return true;
} else {
return false; }
}//end of if;
}//end of verify
}//enfd of class
Just trying to get pass and return true if its the same or false if not
Thanks

Like many, many, many other php users, you are confusing 2 totally different APIs - mysqli and PDO.
Please, choose one, namely PDO, and make your code consistent with it.
Here goes the code with all the useless stuff taken out,
yet with proper things, namely prepared statements, added:
function verify ($un, $pwd)
{
$sql = "SELECT pass FROM User WHERE username = ?"
$sth = $this->conn->prepare($sql);
$sth->execute(array($un));
$pass = $sth->fetchColumn();
return (crypt($pwd, $pass) == $pass);
}
but note that this function of verify should not be a method of mysql class

Related

mysqli prepare statement error "MySQL server has gone away"

I'm struggling to make the jump form Procedural to Object Orientated style so if my code is untidy or flawed please be nice - here I'm passing a couple of posts via jQuery to a class to update a record when the user checks a checkbox:
Here is the database connection
class db {
private $host ;
private $username;
private $password;
private $dbname;
protected function conn()
{
$this->host = "localhost";
$this->username = "root";
$this->password = "";
$this->dbname = "mytest";
$db = new mysqli($this->host, $this->username, $this->password, $this->dbname);
if($db->connect_errno > 0){
die('Unable to connect to database [' . $db->connect_error . ']');
}
return $db;
}
}
Here is the update class
class updOrders extends db {
public $pid;
public $proc;
public function __construct()
{
$this->pid = isset($_POST['pid']) ? $_POST['pid'] : 0;
$this->proc = isset($_POST['proc']) ? $_POST['proc'] : 1;
// $stmt = $this->conn()->query("UPDATE tblorderhdr SET completed = ".$this->proc." WHERE orderid = ".$this->pid);
$stmt = $this->conn()->prepare("UPDATE tblorderhdr SET completed = ? WHERE orderid = ?");
$stmt->bind_param('ii', $this->proc, $this->pid);
$stmt->execute();
if($stmt->error)
{
$err = $stmt->error ;
} else {
$err = 'ok';
}
/* close statement */
$stmt->close();
echo json_encode($err);
}
}
$test = new updOrders;
When I comment out the prepare statement and run the query directly (commented out) it updates, when I try and run it as a prepare statement it returns an error "MySQL server has gone away".
I have looked at your code and I found this.
$stmt = $this->conn()->prepare("UPDATE tblorderhdr SET completed = ? WHERE orderid = ?");
I wrote nearly the same. But I saw you separated the connection from the prepare function.
$db = $this->conn();
$stmt = $db->prepare("UPDATE tblorderhdr SET completed = ? WHERE orderid = ?");
I don't know either why, but it works now.
It would appear that the problem lies within the connection to the database. Here is the (relevant bit of the) updated code:
$db = $this->conn();
$stmt = $db->prepare("UPDATE tblorderhdr SET completed = ? WHERE orderid = ?");
$stmt->bind_param('ii', $this->proc, $this->pid);
$stmt->execute();
When you call $this->conn(), you are creating a new connection object of class mysqli. When no more variables point to the object, PHP will trigger its destructor. The destructor for mysqli will close the connection. This means that if you do not save the return value of this method into a variable, there will be no more references pointing to the object and the connection will be closed.
To fix this, simply save the object and reuse it. Don't connect each time.
$conn = $this->conn();
$stmt = $conn->prepare("UPDATE tblorderhdr SET completed = ? WHERE orderid = ?");
On a side note, creating a class like the one you have db is absolutely pointless. This class doesn't do anything useful. You haven't added any extra functionality to mysqli. You never need to save the credentials in properties. The whole class can be replaced with this code:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'user', 'password', 'test');
$mysqli->set_charset('utf8mb4'); // always set the charset
Then your classes will expect the mysqli object as a dependency.
class updOrders {
public $pid;
public $proc;
public function __construct(mysqli $conn) {
}

Including parent objects in "require"d files

Overview
I connect to a database in index.php, then import my classes.php file using require_once(). However, when connecting to the database, the database connection is undefined.
Code
index.php
$dbh = new PDO("mysql:host=$hostname;dbname=$dbname",$username,$password);
require_once("inc/classes.php");
/* ..... */
if($_POST["form"]=="login"){
//Retrieve values
$e = $_POST["email"];
$p = $_POST["password"];
//Data validation
if(!filter_var($e, FILTER_VALIDATE_EMAIL)||strlen($e)<3) $errors->addError("email", "Please enter a valid email address.");
if(strlen($p)<1) $errors->addError("password", "Please enter a valid password");
$errors->killErrors();
//Log user in
$user = new User($e);
if(!$user->login($p)) $errors->addError("form", "Incorrect username or password.");
$errors->killErrors();
exit("success");
}
inc/classes.php
class User
{
public $id, $email, $data;
public function __construct($e = null){
if(isLoggedIn()){
$stmt = $dbh->prepare("SELECT * FROM `users` WHERE `id`=? LIMIT 1");
$stmt->execute(array($_SESSION["userid"]));
$this->data = $stmt->fetch(PDO::FETCH_ASSOC);
} else $this->email = $e;
}
public function login($p){
//Perform database query for user
$stmt = $dbh->prepare("SELECT `id`, `password` FROM `users` WHERE `email`=? LIMIT 1");
$stmt->execute(array($this->email));
if($stmt->rowCount()<1) return false;
//Check password is correct
$data = $stmt->fetch(PDO::FETCH_ASSOC);
if(!password_verify($p, $data["password"])) return false;
if(!$this->email) exit("User can only be logged in with an email address, not by User ID");
$this->id = $data["id"];
return $this->validate($this->id) ? true : false;
}
}
Output
Notice: Undefined variable: dbh in /var/www/html/foo/public_html/bar/inc/classes.php on line 80
Fatal error: Call to a member function prepare() on null in /var/www/html/foo/public_html/bar/inc/classes.php on line 80
Line 80 is:
$stmt = $dbh->prepare("SELECT `id`, `password` FROM `users` WHERE `email`=? LIMIT 1");
Question
How can I include the database connection in index.php and have the classes.php file accept that PDO object?
You have to make your connection global:
global $dbh;
Because of scope. Done carefully it is OK to use global variables. Many use it too haphazardly and have a tendency to want to globalize all of their variables. I personally do it within the function inside the class to eliminate ambiguity.
http://php.net/manual/en/language.variables.scope.php - as #JayBlanchard writes, you need to reference the connection handle as a global variable.
However, it's much cleaner to pass dependencies into your object. For instance, when instantiating your User, you can pass in the connection.
$user = new User($dbh, $e);
You can then set a private variable for the connection handle. This way, you can change the name of the variable in index.php, or change the way it's instantiated without your User class blowing up due to a change in a different file.

call to member function prepare error

I am having an issue executing the below code. I get an error: Fatal error: Call to a member function prepare() on null in C:\xampp\htdocs... everytime I run it. It errors out right when it is about to query the database for some reason.
I am creating a function to check a username and password, and if it matches, log the user in and so forth. What I am trying to do is feed the outer function a username and a password, then pass those variables to the inner function (checkUser) to retrieve the user and password. Once I have those in an array, I want to compare to see if they match. If they do, then I want to continue on (I left the rest out for simplicity's sake). I don't know why I am getting the error I am getting, especially since it won't even run the 3rd line in the CheckUser without a fatal error.
This is homework, fyi, cards on the table. Just trying to get past this part. Thanks for any help.
function isValidUser($username, $password){
$checker = checkUser($username, $password);
if ($checker[user_email] == $username && $checker[user_pwd] == $password ) {
return TRUE;
}
}
function checkUser($username, $password) {
global $db;
$st = $db -> prepare('SELECT * FROM user WHERE user_email = ? and user_pwd = ?;');
$st -> bindParam(1, $username);
$st -> bindParam(2, $password);
$st -> execute();
return $st -> fetch(PDO::FETCH_ASSOC);
}
try this instead of global $db
$db = $GLOBALS['db'];

Handling my connection variable for login script use [duplicate]

This question already has answers here:
mysqli_query() expects parameter 1 to be mysqli, object given
(3 answers)
Closed 2 years ago.
Currently I am using
$con=mysqli_connect("x","x","x","x");
to handle my database connection on the login script. However, I'm trying to transition this to an OOP style approach such as
$con = new dbclass();
$con->openDB();`
I'm not having any luck with this though.
Warning: mysqli_real_escape_string() expects parameter 1 to be mysqli, object given in C:\xampp\htdocs\c\login.php on line 103
Warning: mysqli_real_escape_string() expects parameter 1 to be mysqli, object given in C:\xampp\htdocs\c\login.php on line 104
Warning: mysqli_query() expects parameter 1 to be mysqli, object given in C:\xampp\htdocs\c\login.php on line 109
Warning: mysqli_fetch_array() expects parameter 1 to be mysqli_result, null given in C:\xampp\htdocs\c\login.php on line 111
Acess denied, wrong username or password?
This is the method I'm using to do this.
function openDB() {
$config = include("/assets/configs/db_config.php");
$conn = mysqli_connect($config["host"] , $config["username"], $config["password"],$config["dbname"]);
// 1. Create a database connection
if (!$conn)
{
$this->error_msg = "connection error could not connect to the database:! ";
return false;
}
$this->conn = $conn;
return true;
}
Can anyone make any suggestions. Do I need to use mysqli_connect() somewhere within my method. Or even better, within my db_config file :
<?php
return array("host"=>"x", "dbname"=>"x", "username"=>"x", "password"=>"x");
mysqli_report(MYSQLI_REPORT_ERROR);
?>
include() does not cause the variables defined therein to become an array - they are automatically imported into the scope in which you are calling the function. Since you are not defining $config inside the include file, you're never accessing the array.
So, $config = include('your_script.php') doesn't do what you likely think it does.
You should update the function as follows (and change the array definition inside db_config.php to define $host, $username, $password and $dbname).
function openDB()
{
include("/assets/configs/db_config.php");
$conn = mysqli_connect($host, $username, $password, $dbname);
// 1. Create a database connection
if(!$conn)
{
$this->error_msg = "connection error could not connect to the database:! ";
return false;
}
$this->conn = $conn;
return true;
}
That having been said, this isn't the best way to handle DB connections in an OOP application. If you need to move the config file, you have to update the Database class. It would be better to pass in the variables to your openDB() function as parameters, and then retrieve them from a config script in your controller somewhere.
For example, the following is much better practice:
function openDB($username, $password, $dbname, $host = 'localhost')
{
$conn = mysqli_connect($host, $username, $password, $dbname);
if(!$conn)
{
$this->error_msg = 'connection error could not connect to the database!';
return false;
}
$this->conn = $conn;
return true;
}
Try using this only initiate like $db = new db(); no need to open db it will already connect
EDIT
here is code of db_config.php
$db_host = 'localhost';
$db_user = 'root';
$db_password = '';
$db_name = 'bs_admin';
class db
{
public $dbh;
public $error;
public $error_msg;
// Create a database connection for use by all functions in this class
function __construct()
{
require(dirname(dirname(__FILE__)) . '/config/db_config.php');
if($this->dbh = mysqli_connect($db_host, $db_user, $db_password, $db_name))
{
// Set every possible option to utf-8
mysqli_query($this->dbh, 'SET NAMES "utf8"');
mysqli_query($this->dbh, 'SET CHARACTER SET "utf8"');
mysqli_query($this->dbh, 'SET character_set_results = "utf8",' .
'character_set_client = "utf8", character_set_connection = "utf8",' .
'character_set_database = "utf8", character_set_server = "utf8"');
}
else
{
// Log an error if the connection fails
$this->error = true;
$this->error_msg = 'Unable to connect to DB';
}
// Add a row to any table
public function insert($table,$field_values)
{
$query = 'INSERT INTO ' . $table . ' SET ' . $field_values;
mysqli_query($this->dbh,$query);
}
}

Cant pass mysqli connection to class

I am trying to pass an mysqli database connection to a php class. The code I have so far (cut down for simplicity) is as follows:
db.php
$db_host = 'localhost';
$db_name = 'dbname';
$db_user = 'username';
$db_password = 'password';
$db = array('db_host'=>$db_host,
'db_name'=>$db_name,
'db_user'=>$db_user,
'db_password'=>$db_password);
$dbCon = new mysqli( $db['db_host'],
$db['db_user'],
$db['db_password'],
$db['db_name']);
if (mysqli_connect_errno())
{
die(mysqli_connect_error()); //There was an error. Print it out and die
}
index.php
<?php
require_once($_SERVER["DOCUMENT_ROOT"] . "/db.php");
$sql = "SELECT id FROM usr_clients";
$stmt = $dbCon->prepare( $sql );
if ($stmt)
{
$stmt->execute();
$stmt->bind_result($id);
while($stmt->fetch())
{
$cl = new Client($id, $dbCon);
$cl->doIt();
}
$stmt->close();
}
?>
client.php
<?php
Class Client
{
private $con;
public static $clientCount = 0;
public function __construct( $id, $con )
{
$this->con = $con;
$sql = "SELECT id FROM usr_clients WHERE id = $id";
$stmt = $this->con->prepare( $sql );
if ($stmt)
{
echo "it worked!";
}
else
{
echo "it failed";
}
}
}
?>
Now the index.php page successfully recognises the database connection declared in db.php, and returns a list of all clients. It then loops through each client, and creates a "client" object, passing it the database connection.
It is here that the problem seems to start. In the client class, the database connection is not recognised. I get multiple errors on the page saying "it failed". In the logs, there is a line about calling prepare() on a non object.
Can anyone explain why the connection works in index.php, but not in the client class?
Thanks
Your main problem is assumptions.
You are assuming that there is no connection passed, judging by indirect consequence.
But a programmer should be always logically correct in their reasoning.
Talking of connection? Verify the very connection. var_dump($con) in the constructor. var_dump($this->con) in the method. If it fails - only now you can blame connection and start for the solution.
If not - there is no reason in looking for another connection passing method. Yet it's time to find the real problem.
If your query fails, you have to ask mysql, what's going on, using $this->con->error, as this function will provide you with a lot more useful information than simple "it fails". The right usage I've explained here: https://stackoverflow.com/a/15447204/285587

Categories