Select 2 columns with PHP PDO Query - php

I'm pretty new to PHP and PDO and I'm trying to make a simple login system. Now, I'm trying to fetch the id and password from my table to compare with the password that the user input(I'm using one way encryption with salt). So, now the problem is, when I do $password = $stmt->fetchColumn(1) only, my login system works. Now when I try to get the id by doing $id = $stmt->fetchColumn(0) just before $password, I cannot login anymore and I get my "Wrong Username/Password" error.
Now I'm pretty sure that I'm doing something wrong with the fetchColumn but I can't figure it out.
Here's a code snippet that works:
$con = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
//set how pdo will handle errors
$con->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
//this would be our query.
$sql = "SELECT id, password FROM user_admin WHERE email = :email";
//prepare the statements
$stmt = $con->prepare( $sql );
//give value to named parameter :email
$stmt->bindValue( "email", $this->email, PDO::PARAM_STR );
$stmt->execute();
$password = $stmt->fetchColumn(1);
Now the following doesn't work. Notice that this happens when I added the $id:
$con = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
//set how pdo will handle errors
$con->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
//this would be our query.
$sql = "SELECT id, password FROM user_admin WHERE email = :email";
//prepare the statements
$stmt = $con->prepare( $sql );
//give value to named parameter :email
$stmt->bindValue( "email", $this->email, PDO::PARAM_STR );
$stmt->execute();
$id = $stmt->fetchColumn(0); //That's the problem
$password = $stmt->fetchColumn(1);
Any help is greatly appreciated.

From the documentation:
PDOStatement::fetchColumn — Returns a single column from the next row of a result set
Each time you call fetchColumn it advances to the next row of the result set.
Try using PDOStatement::fetch instead to fetch the entire row as an an array and then accessing the values from there.
$stmt->execute();
$row = $stmt->fetch();
$id = $row[0];
$password = $row[1];

Related

PDO Insert foreach

I am trying to insert an array of values multiple times into a table.
I have a simple array that is generated by a user checking a box and that's what gets added to the array, I then want to insert each value into a table, I thought I could do it with a foreach loop and iterate $i but it appears I can't, I don't need to worry about security or anything as this is internally used by two people.
here is what I have:
foreach($detailsinvoice as $desc){
$conn3 = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql3 = "INSERT INTO
xero_invoices (ContactName, Description)
VALUES (:ContactName, :Description)";
$st3 = $conn3->prepare ( $sql3 );
$st3->bindValue( ":ContactName", $this->ContactName, PDO::PARAM_STR );
$st3->bindValue( ":Description", $desc, PDO::PARAM_STR );
$st3->execute();
$this->InvoiceNumber = $conn3->lastInsertId();
$conn3 = null;
}
This was my first attempt but gathered that the connection can only be used once then exits, so I tried an iteration but again I learnt that you can't do that with the PDO statement.
$i = 3;
foreach($detailsinvoice as $desc){
$conn[$i] = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql[$i] = "INSERT INTO
xero_invoices (ContactName, Description)
VALUES (:ContactName, :Description)";
$st[$i] = $conn[$i]->prepare ( $sql[$i] );
$st[$i]->bindValue( ":ContactName", $this->ContactName, PDO::PARAM_STR );
$st[$i]->bindValue( ":Description", $desc, PDO::PARAM_STR );
$st[$i]->execute();
$this->InvoiceNumber = $conn[$i]->lastInsertId();
$conn[$i] = null;
$i++;
}
detailsinvoice is the array and the ContactName will be the same each time (the Contactname works just need to figure out looping the array)
I would appreciate if someone could point me in the right direction.
Feature of prepared statements is that you can prepare a statement once and then execute it multiple times, so your code can be rewritten as:
// Create a connection
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql = "INSERT INTO
xero_invoices (ContactName, Description)
VALUES (:ContactName, :Description)";
// Create a statement
$st = $conn->prepare ($sql);
foreach ($detailsinvoice as $desc) {
// bind values and execute statement in a loop:
$st->bindValue( ":ContactName", $this->ContactName, PDO::PARAM_STR );
$st->bindValue( ":Description", $desc, PDO::PARAM_STR );
$st->execute();
$this->InvoiceNumber = $conn->lastInsertId();
}
// this is optional
$conn = null;
I have no idea where you got the idea a connection can only be used once from. You should connect only once in a script. Then as long as you store and pass around the $conn variable to any functions you may use (Scope of course is relevant here) you can use it as many times as you like.
// connect ONCE per script
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
// write the query once
$sql = "INSERT INTO xero_invoices (ContactName, Description)
VALUES (:ContactName, :Description)";
// and prepare it once.
$st = $conn->prepare ( $sql );
// now loop over the array of parameters any number of times you like
foreach($detailsinvoice as $desc){
$st->bindValue( ":ContactName", $this->ContactName, PDO::PARAM_STR );
$st->bindValue( ":Description", $desc, PDO::PARAM_STR );
$st->execute();
// this line looks wrong, as $this->InvoiceNumber will get overwritten
// each time round the loop
//$this->InvoiceNumber = $conn->lastInsertId();
// maybe you ment this, so at least you would have them all????
$this->InvoiceNumber[] = $conn->lastInsertId();
// or I have to assume you are going to add another query HERE
// that will use that ID
}
The concept of a prepared statement is that it is passed to the database, compiled, optimised and saved in the database almost like a stored proceedure.
Once prepared it can be used again and again. All you do is put new values into your parameters each time you execute it.

CREATE USER fails with Mysqli prepared statements

I'm trying to create a simple PHP script to create and assign attributes to an SQL user. The query works fine if no parameters are used, but fails otherwise.
Works fine
$conn = new mysqli('127.0.0.1', 'root', 'pass');
$sql = "CREATE USER 'newuser'#'localhost' IDENTIFIED BY 'password'";
$stmt = $conn->prepare($sql);
$stmt->execute();
Both username and password are ?
$conn = new mysqli('127.0.0.1', 'root', 'pass');
$sql = "CREATE USER '?'#'localhost' IDENTIFIED BY '?'";
$stmt = $conn->prepare($sql);
$uname = "carn";
$pass = "pass";
$stmt->bind_param('ss', $uname, $pass);
$stmt->execute();
Both username and password are ?
$conn = new mysqli('127.0.0.1', 'root', 'pass');
$sql = 'CREATE USER "?"#"localhost" IDENTIFIED BY "?"';
$stmt = $conn->prepare($sql);
$uname = "carn";
$pass = "pass";
$stmt->bind_param('ss', $uname, $pass);
$stmt->execute();
Error in syntax, check documentation
$conn = new mysqli('127.0.0.1', 'root', 'pass');
$sql = "CREATE USER ?#'localhost' IDENTIFIED BY ?";
$stmt = $conn->prepare($sql);
$uname = "carn";
$pass = "pass";
$stmt->bind_param('ss', $uname, $pass);
$stmt->execute();
Error in syntax, check documentation
$conn = new mysqli('127.0.0.1', 'root', 'pass');
$sql = "CREATE USER `?`#'localhost' IDENTIFIED BY `?`";
$stmt = $conn->prepare($sql);
$uname = "carn";
$pass = "pass";
$stmt->bind_param('ss', $uname, $pass);
$stmt->execute();
I'm not sure where to go from here. This might be an issue with the way I'm using quotes I saw two related questions here on SO but none of them answered properly.
With prepared statement you can use only limited subset of queries. Create user not included.
You can try INSERT into mysql.user table, something like
INSERT INTO `mysql`.`user` (Host,User,Password)VALUES(?,?,password(?));
Besides, with users created dynamically you are doing something wrong
Don't put single quotes around the ?, bind_param() will take care of it.
However, there is another issue that you can't use placeholders for CREATE USER statements in MySQL.
See How to write "create user ?" with MySQL prepared statement for a way of doing it.

PHP + MSSQL using PDO with Named Parameters not '?'

I'm about to commence building a site using mssql and php.
I plan to use PDO's, however, as I currenlty believe its not possible to use named parameters.
Currently in MySQL I would use named placeholders in my query as such;
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql = "SELECT *
FROM table
LIMIT :numRows";
$st = $this->conn->prepare( $sql );
$st->bindValue( ":numRows", $numRows, PDO::PARAM_INT );
However when using MSSQL;
$conn = new PDO("mysql:host=" . DB_HOST .";dbname=" . DB_NAME, DB_USER, DB_PASSWORD);
$sSQLInsert = "SELECT TOP ? *
FROM table";
$aParams = array($iLimit);
$st = sqlsrv_query($dbhandle, $sSQLInsert, $aParams)){}
My worry appears when I have many parameters that need to be bound. Managing the order of them and dancing back and forth between query-parameters doesnt seem ideal.
So my question; is it posible to use named placeholders with MSSQL?
This would be a simple script to write an check, however I found documentation and an example! The answer is YES! Name parameters works with PDO_MSSQL.
https://msdn.microsoft.com/en-us/library/ff628166(v=sql.105).aspx
$stmt = null;
$contact = "Sales Agent";
$stmt = $conn->prepare("select * from Person.ContactType where name = :contact");
$stmt->bindParam(':contact', $contact);
$contact = "Owner";
$stmt->execute();
No You cannot use named Placeholder with sqlsrv_ or any other extension.
This is a feature of PDO only.
I plan to use PDO's, however, as I currenlty believe its not possible
to use named parameters.
You can do it with SQL server:
$sql = "SELECT TOP :numRows *
FROM table";
$st = $this->conn->prepare( $sql );
$st->bindValue( ":numRows", $numRows, PDO::PARAM_INT );
$st->execute();
var_dump($st->fetch());
It is not about the server, it is more about the driver, this PDO advantage since it is compatible with most database. You don't have to change your code, just the connection.
You might have luck looking at the following PDF (auto download of pdf):
http://tinyurl.com/orc2xkc
It has examples binding with variables and arrays.
$sql = ‘select Title,
FirstName,
MiddleName,
LastName
from SalesLT.Customer
where Title = :title and CustomerId<10’;
$query = $conn->prepare($sql);
$title = ‘Mr.’;
$query->bindParam(‘:title’, $title);
$query->execute();
In the meantime I will look up info on mssql driver to use because that apparently plays into it.
Edit ... As for the driver look at the comments under this question:
From PDO to SQLSRV
Many thanks for all the replies to this. After some time I've managed to get it working, so in answer to my question; Yes it is possible to use Named Placeholders with MSSQL.
After installing the SQLSRV PDO extension, placeholders can be used as such;
$database = "";
$server = "";
$conn = new PDO( "sqlsrv:server=$server ; Database = $database", DB_USER, DB_PASSWORD);
$sql = "SELECT * FROM Table WHERE MemberID =:MemberID";
$iMemberID = 5;
$st = $conn->prepare($sql);
//named placeholders within the execute() as an array.
$st->execute(array(':MemberID'=>$iMemberID));
//OR using bind param..
$st->bindParam(':MemberID', $iMemberID);
while ($row = $st->fetch()){
echo "<pre>";
var_dump($row);
echo "</pre>";
}
Thanks to Drew Pierce for the link to the drivers and pdf and everyone else for the help.

mysql statement not working properly in php code

Following is the code in my script. the $sql statement is properly working when executed in phpmyadmin. But it dosent work in the following code. displaying only one row of data.
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql="SELECT DISTINCT productId FROM bid WHERE userId =:id";
$st = $conn->prepare( $sql );
$st->bindParam( ":id", $_SESSION['id'], PDO::PARAM_INT );
$st->execute();
$data=$st->fetch(PDO::FETCH_ASSOC);
$conn=null;
print_r($data);
In both methods, replace
$data = $st->fetch(PDO::FETCH_ASSOC);
with the code given.
One of the method would be:
$data = $st->fetchAll(PDO::FETCH_ASSOC);
Loop
while( $data = $st->fetch(PDO::FETCH_ASSOC) )
print_r($data);
$conn=null;

PHP PDO UPDATE not updating data

I am having a tough time updating data using PDO. These are the two options that i've tried. None has actually updated the database, however.
Query 1:
$dateLastLoggedIn = date("Y-m-d H:i:s");
$username = mysql_real_escape_string($_POST['User']);
$sth = $dbh->prepare("UPDATE users SET dateLastLoggedIn = ? WHERE username = ?");
$sth->execute(array($dateLastLoggedIn,$username));
print_r($sth->queryString); just prints out UPDATE users SET dateLastLoggedIn = ? WHERE username = ?
Query 2:
$dateLastLoggedIn = date("Y-m-d H:i:s");
$username = mysql_real_escape_string($_POST['User']);
$sql = "UPDATE users SET dateLastLoggedIn = '".$dateLastLoggedIn."' WHERE username = '".$username."'";
$sth = $dbh->prepare($sql);
$sth->execute();
print_r($sth->queryString); prints out UPDATE users SET dateLastLoggedIn = '2012-08-03 13:36:32' WHERE username = 'testuser'
The second option generates the correct query but it doesn't actually update the data. I can manually run the generated script and it works, but not through the execute(). Anything i'm doing wrong? I'm still new to PDO, so it may be a simple fix.
SOLVED: see my last comment under the accepted answer.
getting connection :
function getConnection(){
$dbhost="127.0.0.1";
$dbuser="application";
$dbpass="password";
$dbname="abc";
$dbh = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
try {
$dbh = getConnection();
$sth = $dbh->prepare("UPDATE users SET dateLastLoggedIn = :dateLastLoggedIn WHERE username = :username ");
$sth->bindParam('dateLastLoggedIn',$dateLastLoggedIn);
$sth->bindParam('username',$username );
$sth->execute();
$dbh = null; // after done
} catch(PDOException $e) {// simple exception handling
error_log($e->getMessage(), 3, '/var/tmp/php.log');
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
Also, try to wrap this in try catch to see the error
print_r($sth->queryString); just prints out UPDATE users SET dateLastLoggedIn = ? WHERE username = ?
That's what will happen with PDO prepared queries.
If you're using PDO, mysql_real_escape_string isn't going to work. At all. It requires an existing connection via mysql_connect. Your username value is effectively blank.

Categories