How to migrate mysqli to pdo - mysqli

Hi I was wondering how I would migrate a mysqli php file to use PDO. Would anyone be able to take a look at my code and see if I'm on the right track?
This is my original (mysqli) code:
<?php
// connecting to database
$conn = new mysqli('xxxxxx', 'xxxxxx', 'password', 'xxxxxx');
$match_email = 'email';
$match_passhash = 'passhash';
if (isset($_POST['email'])) {
$clean_email = mysqli_real_escape_string($conn, $_POST['email']);
$match_email = $clean_email;
}
if (isset($_POST['passhash'])) {
$clean_passhash = mysqli_real_escape_string($conn, $_POST['passhash']);
$match_passhash = sha1($clean_passhash);
}
$userquery = "SELECT email, passhash, userlevel, confirmed, blocked FROM useraccounts
WHERE email = '$match_email' AND passhash = '$match_passhash'
AND userlevel='user' AND confirmed='true' AND blocked='false';";
$userresult = $conn->query($userquery);
if ($userresult->num_rows == 1) {
$_SESSION['authorisation'] = 'knownuser';
header("Location: userhome.php");
exit;
} else {
$_SESSION['authorisation'] = 'unknownuser';
header("Location: userlogin.php");
exit;
}
?>
And this is my attempt to migrate it to PDO:
<?php
// connecting to database
$dbh = new PDO("mysql:host=xxxxxx; dbname=xxxxxx", "xxxxxx", "password");
$match_email = 'email';
$match_passhash = 'passhash';
if (isset($_POST['email'])) {
$clean_email = mysqli_real_escape_string($conn, $_POST['email']);
$match_email = $clean_email;
}
if (isset($_POST['passhash'])) {
$clean_passhash = mysqli_real_escape_string($conn, $_POST['passhash']);
$match_passhash = sha1($clean_passhash);
}
$userquery = "SELECT email, passhash, userlevel, confirmed, blocked FROM useraccounts
WHERE email = ':match_email' AND passhash = ':match_passhash' AND
userlevel='user' AND confirmed='true' AND blocked='false';";
$stmt = $dbh->prepare($query);
$stmt->bindParam(":match_email", $match_email);
$stmt->bindParam(":match_passhash", $match_passhash);
$stmt->execute();
$userresult = $conn->query($userquery);
if ($userresult->num_rows == 1) {
$_SESSION['authorisation'] = 'knownuser';
header("Location: userhome.php");
exit;
} else {
$_SESSION['authorisation'] = 'unknownuser';
header("Location: userlogin.php");
exit;
}
?>
I'm also not sure how to count the number of rows returned in PDO.
If anyone would be able to help me out that wold be very great.
A million thanks in advance!

When using prepared statements and $stmt->bindValue() or $stmt->bindParam() you do not need to escape values with mysqli_real_escape_string(), PDO will do that for you.
Just remember to set a correct data type for the value. That is the third argument in the bind functions and it is a string by default so your code here is fine. I would only use bindValue() instead of bindParam() as you do not need references.
$stmt->execute() will run your prepared statement as a query. The other $conn->query() does not work with prepared statements. It is for raw queries, like you used to have with MySQLi.
When $stmt->execute() runs your response is saved in the $stmt object. For row count use $stmt->rowCount().

Related

Getting sum in PHP MySQL

I want to get sum of integers that are selected from mysql
Here is my code
<?php
Include 'init.php';
$page = '2459';
$ttl = array();
$search = $db->link->query("SELECT id,packid,rating FROM pakrate WHERE packid LIKE '%$q%'");
if($search->num_rows>0){
while($result=$search->fetch_assoc()){
$ttl[] = $row['rating'];
echo $ttl;
echo $result[SUM('rating')];
}
}
else {
echo "no such query";
}
So what I am doing wrong here, any other suggestions?
Just run the sum in your query
<?php
Include 'init.php';
$page = '2459';
$ttl = array();
// Not sure why you're doing this but there should only be one leading connection ($conn->query) unless you're doing some object item elsewhere in init.
// I would also use prepared statements since they're more secure:
$q = "%$q%"; // create your like variable, wherever $q is coming from??
$query = "SELECT sum(rating) from pakrate WHERE packid LIKE ?);
$stmt = $db->prepare($query); // assuming $db is your connection variable
if($stmt){
$stmt->bind_param("s",$q); // Bind the variable in
$stmt->execute(); // Execute
$stmt->bind_result($rating); // Bind the result variable
$stmt->store_result(); // Store it so you can get num_rows
$rows = $stmt->num_rows; // assign rows found
if($rows > 0){
while($stmt->fetch()){ // Loop the result
$ttl[] = $rating; // add to your array
// You can't echo an array like this.... echo $ttl;
// if you really want to, print_r($ttl);
}
}
$stmt->close(); // Close it
}
?>

change mysqli check exit and insert into pdo statement

i want to change my mysqli check exist and insert into pdo.. my statement look like below:
<?php
$addSearch = preg_replace('/[^a-zA-Z0-9_ %\[\]\.\(\)%&-]/s', '', $search);
if ($CheckMusic = $mysqli->query("SELECT * FROM search WHERE term='$addSearch'")) {
$CheckRow = mysqli_fetch_array($CheckMusic);
$CheckId = $CheckRow['id'];
$CheckCnt = $CheckMusic->num_rows;
$CheckMusic->close();
} else {
printf("Error: %s\n", $mysqli->error);
}
$Now = strtotime("now");
$addSearch = $mysqli->escape_string($addSearch);
if ($CheckCnt < 1) {
$mysqli->query("INSERT INTO search (term, datetime) VALUES('$addSearch','$Now') ") or die(mysqli_error());
} else {
$mysqli->query("UPDATE search SET datetime='$Now' WHERE id='$CheckId'") or die(mysqli_error());
}
?>
hope someone can help with sample if can ;q thanks for your advance!
<?php
$addSearch = preg_replace('/[^a-zA-Z0-9_ %\[\]\.\(\)%&-]/s', '', $search);
$CheckMusic = $mysqli->query("SELECT * FROM search WHERE term='$addSearch'");
$Now = strtotime("now");
if($CheckMusic->num_rows == 0){
$mysqli->query("INSERT INTO search (term, datetime) VALUES('$addSearch','$Now') ") or die(mysqli_error());
}else{
$CheckRow = mysqli_fetch_array($CheckMusic);
$CheckId = $CheckRow['id'];
$addSearch = $mysqli->escape_string($addSearch);
$mysqli->query("UPDATE search SET datetime='$Now' WHERE id='$CheckId'") or die(mysqli_error());
}
I hope it will work.

Hashing password in register and account settings

I am get login errors when i test my script by logining under my own account. Do you think hashing passwords twice a bad practice?
I have hashed the users password twice in my website. Once, when they register and once, when they update their password in account update. Also i am using bcrypt method and cost of bcrypting is 10 on both hashings and i am on localhost server.
///// this is the code in register.php page
<?php
if(isset($_POST['registeruser'])) {
session_start();
$FName = $_POST['regfname'];
$LName = $_POST['reglname'];
$Email = mysqli_real_escape_string($conn, $_POST['regemail']);
$origignalpassword = preg_replace('#[^a-z0-9_]#i', '',
$_POST['regpassword']);
$Passwordw = $_POST['confirmedpassword'];
$infosql = "SELECT * FROM users WHERE useremail = '".$Email."'";
$result = mysqli_query($conn,$infosql);
if(mysqli_num_rows($result)>=1)
{
echo "Email already taken.";
}
else if(mysqli_num_rows($result) !=1 && $Passwordw ==
$origignalpassword) {
$Passwordhash = password_hash($Passwordw,
PASSWORD_BCRYPT, array('cost' => 10));
$sql = $conn->query("INSERT INTO users(firstname,
lastname, useremail, Passwordcell) Values('{$FName}',
'{$LName}','{$Email}','{$Psswordhash}')");
header('Location: login.php');
} else {
echo 'Please check your password:' . '<br>';
}
}
?>
//// Below code is the code in my update.php page
<?php session_start();
if(isset($_SESSION['user_id'])) {
} else {
header('Location: login.php');
}
$user = $_SESSION['userid'];
$myquery = "SELECT * FROM users WHERE `userid`='$user'";
$result = mysqli_query($conn, $myquery);
$row = mysqli_fetch_array($result, MYSQLI_BOTH);
$_SESSION['upd_fnames'] = $row['firstname'];
$_SESSION['upd_lnames'] = $row['Lastname'];
$_SESSION['upd_emails'] = $row['useremail'];
$_SESSION['upd_passwords'] = $row['Passwordcell'];
$_SESSION['upd_phone'] = $row['phonenum'];
$_SESSION['upd_bio'] = $row['biography'];
?>
<?php
if (isset($_POST['updateme'])) {
$updfname = $_POST['upd_fnames'];
$updlname = $_POST['upd_lnames'];
$updemail = $_POST['upd_emails'];
$updphone = $_POST['upd_phone'];
$upd_pswd = $_POST['upd_passwords'];
$biography = $_POST['update_biography'];
$Pswod = password_hash($upd_pswd, PASSWORD_BCRYPT,
array('cost' => 10));
$sql_input = $mysqli->query("UPDATE users SET firstname = '{$updfname}', Lastname = '{$updlname}', Phonenum = '{$updphone}', useremail = '{$updemail}', Passwordcell = '{$Pswod}', biography = '{$biography}' WHERE userid=$user");
header('Location: Account.php');
}
else
{
}
?>
Your problem could be just a typo, in your registration script, instead of $Passwordhash you wrote:
"INSERT INTO users(..., Passwordcell) Values(...,'{$Psswordhash}')"
Nevertheless there are other problems with your code, and since you asked for advise, i would like to share my thoughts.
Probably the biggest problem is, that your code is vulnerable to SQL-injection. Switch to prepared statements as soon as you can, writing code will become even easier than building the query as you did, and both MYSQLI and PDO are supporting it. This answer could give you a start.
Passwords should not be sanitized. Remove the line $origignalpassword = preg_replace('#[^a-z0-9_]#i', '', $_POST['regpassword']), and just pass the input directly to the hash function password_hash($_POST['regpassword'], PASSWORD_DEFAULT). The password_hash() function works with any type of input.
It is a good habit to place an exit after each redirection, otherwise the script will continue executing. header('Location: login.php', true, 303); exit;
Do you really have reason to put the user info into the session? Instead of $_SESSION['upd_fnames'] = $row['firstname']; i would fetch the information on demand from the database. With fetching it from the database you can be sure that the information is actually set (is not null) and is up to date, you can avoid a state and you get a bit more REST full.
Then last but not least i would recommend to follow some style rules, like starting variable names always with a small letter. You can avoid some silly typos and it makes your code more readable.

Email validation MySQL and PHP

I want to check if email already exists in the DB, starting at this and need some help. Here is the code:
<?php
require_once('includes/connects.php');
$username = $_POST['username'];
$nome = $_POST['nome'];
$password = sha1($_POST['password']);
$email = $_POST['email'];
$checkmail = mysql_query("SELECT email FROM utilizadores WHERE email = '$email'");
$result = $conn->query($checkmail);
if($result->num_rows == 0){
$querygo = "INSERT INTO utilizadores (username, nome, password, email) VALUES ('$username', '$nome', '$password', '$email'";
$result = $conn->query($querygo);
header('Location: index.php');
} else {
echo 'DONT WORK';
}
This is the error:
Fatal error: Call to a member function query() on a non-object in
C:\Sites\deca_13L4\deca_13L4_23\MiniProjeto\bussaco\registo.php on
line 12 Warning: Unknown: 1 result set(s) not freed. Use
mysql_free_result to free result sets which were requested using
mysql_query() in Unknown on line 0
Looking at your code, unsure what value this has in the mix of everything since that is exactly where the error occurs:
$result = $conn->query($checkmail);
So I would change your code to be like this:
<?php
require_once('includes/connects.php');
$username = $_POST['username'];
$nome = $_POST['nome'];
$password = sha1($_POST['password']);
$email = $_POST['email'];
$checkmail = mysql_query("SELECT email FROM utilizadores WHERE email = '$email'");
if(!$checkmail){
$querygo = "INSERT INTO utilizadores (username, nome, password, email) VALUES ('$username', '$nome', '$password', '$email'";
$result = $conn->query($querygo);
header('Location: index.php');
} else {
echo 'DONT WORK';
}
But that said, it’s unclear to me where the actual needed mysql_connect comes from. Is that in require_once('includes/connects.php');? I hope so. Otherwise mysql_query won’t work no matter what. To execute a query you need a connection.
just make your code as simple as you can. So here:
<?php
require_once('includes/connects.php');
$username = $_POST['username'];
$nome = $_POST['nome'];
$password = sha1($_POST['password']);
$email = $_POST['email'];
$checkmail = mysql_query("SELECT email FROM utilizadores WHERE email = '$email'");
$num_rows = mysql_num_rows($checkmail);
if($num_rows){
$querygo = "INSERT INTO utilizadores (username, nome, password, email) VALUES ('$username', '$nome', '$password', '$email'";
$result = mysql_query($querygo);
header('Location: index.php');
} else {
echo 'DONT WORK';
}

Zend authenticate returns white screen

This is the most frustrating ever. It is nearly impossible to find errors when all you get is a white screen!!!
This code is used on other projects and it works fine there so syntactically, it is correct. But SOMETHING must be wrong in the configuration...
Here is the code:
protected function _process($values)
{
// Get our authentication adapter and check credentials
$adapter = $this->_getAuthAdapter();
$adapter->setIdentity($values['username']);
$adapter->setCredential($values['password']);
$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($adapter);
if ($result->isValid()) {
$user = $adapter->getResultRowObject();
$auth->getStorage()->write($user);
return true;
}
return false;
}
protected function _getAuthAdapter()
{
$dbAdapter = Zend_Db_Table::getDefaultAdapter();
$authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
$authAdapter->setTableName('Users')
->setIdentityColumn('username')
->setCredentialColumn('password')
->setCredentialTreatment('md5(?)');
return $authAdapter;
}
This is in my auth controller and gets called after I set up the adapter, etc. If I put a die("foo"); right before the $result line, I see it. If I put it right after the $result line, I get a WSOD and the system stops. I know there is not enough here for anyone to debug my code but I was hoping someone else had had this problem and could give me a hint as to what to try to fix this??? I have double checked the database, the column names, etc. I need to know what kinds of things may make the line:
$result = $auth->authenticate($adapter);
result in a white screen of death??? Any ideas? I have all error display turned on in application.ini.
I am running Zend 1.11.12 on this server. Does that make a difference? The server where it is working is running is running 1.12.0-9
Thanks for any ideas you might have.
EDIT::: I added code for my _getAuthAdapter.
Enable the error reporting for your app. Set all error reporting to 1 in your configs/application.ini file -
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
resources.frontController.params.displayExceptions = 1
Also, instead of returning true or false, try to print a message, or redirect to a different page to know.
Try a var_dump on the $adapter to see the resulting object.
I've never used Zend_Auth to authenticate. You should be able to do that with your adapter. (assuming your $adapter is an instance of Zend_Auth_Adapter_DbTable for example)
$adapter = $this->_getAuthAdapter();
// this will tell you if there's something wrong with your adapter
if (!($adapter instanceof Zend_Auth_Adapter_DbTable)) {
throw new Exception('invalid adapter');
}
$adapter->setIdentity($values['username']);
$adapter->setCredential($values['password']);
$result = $adapter->authenticate();
if ($result->isValid()) {
}
I tried like below,
public function loginAction() {
$this->_helper->layout->disableLayout();
$users = new Application_Model_DbTable_Admin();
$this->_redirector = $this->_helper->getHelper('Redirector');
$form = new Application_Form_LoginForm();
$this->view->form = $form;
if ($this->getRequest()->isPost()) {
if ($form->isValid($_POST)) {
$consumer = new Zend_OpenId_Consumer();
$username = $this->_request->getPost('username');
$password = $this->_request->getPost('password');
if ($username <> '' && $password <> '') {
$auth = Zend_Auth::getInstance();
$authAdapter = new Zend_Auth_Adapter_DbTable($users->getAdapter(), 'admin');
$authAdapter->setIdentityColumn('username')
->setCredentialColumn('password');
$authAdapter->setIdentity($username)
->setCredential(md5($password));
$result = $auth->authenticate($authAdapter);
if ($result->isValid()) {
$storage = new Zend_Auth_Storage_Session();
$storage->write($authAdapter->getResultRowObject());
$this->_auth_user = $auth->getStorage()->read();
$this->_redirect('admin/index/');
}
else
$this->view->errorMessage = "Invalid username or password. Please try again.";
}
else
$this->view->errorMessage = "Username or password should not be empty!!!.";
}
}
}
If your Adapter doesn't work try it:
public function _getAuthAdapter() {
$authAdapter = new Zend_Auth_Adapter_DbTable(Zend_Db_Table::getDefaultAdapter());
$authAdapter->setTableName('table_name')
->setIdentityColumn('user_name')
->setCredentialColumn('password');
return $authAdapter;
}
And in application.ini
resources.db.isDefaultTableAdapter = true