Using prepared MySQLi statements to produce associative array - php

I've read a few related questions to this, but in each case I've been unable to get their code to work in my context.
Following some injection attempts, I am trying to implement prepared statements into my site, while changing as little code as possible. Importantly, I want the responses to my SELECT queries to by outputted as associative arrays: e.g. $row['name'].
Here is an example of code that I have right now (without preprepared statements):
// Create connection
$db = new mysqli('localhost', 'username', 'password', 'seatingplan');
if($db->connect_errno > 0){
die('Unable to connect to database [' . $db->connect_error . ']');
}
// Get class name
$sql = <<<SQL
SELECT *
FROM `class`
WHERE `userid` = '$userid'
AND `classid` = '$classid'
SQL;
if(!$result = $db->query($sql)){
die('There was an error running the query [' . $db->error . ']');
}
while($row = $result->fetch_assoc()){
$classname = $row['classname'] ;
}
Is there a straightforward way of adapting this for prepared statements? Based on other questions, this is as far as I've got (but it doesn't work - it only returns 1 for each row, rather than the actual variable):
$stmt = $db->prepare("SELECT *
FROM `class`
WHERE `userid` = ?
AND `classid` = ?");
$stmt->bind_param("ss", $userid, $classid);
$result = $stmt->execute();
$stmt->store_result();
while($data = $stmt->fetch()){
echo $data ;
}

Just define the array and use it for example in your code:
$stmt = $db->prepare("SELECT *
FROM `class`
WHERE `userid` = ?
AND `classid` = ?");
$stmt->bind_param("ss", $userid, $classid);
$stmt->execute();
$result=$stmt->get_result();
$row= array();
$i=0;
while ($data = $result->fetch_assoc())
{
$row[$i]['name']=$data['name'];
$i++;
}
echo $row;

Related

PHP Multiple Prepared Statements

I would like to execute two statements and print the results within a while loop. Each statement will select data from two different tables.
I'm not sure the best way to approach this.
My code so far is as follows;
$conn = new mysqli('localhost', 'user', 'password', 'db');
if ($conn->connect_errno > 0) {
die('Unable to connect to database [' . $conn->connect_error . ']');
}
$curDate = date("Y-m-d");
//first stmt
$stmt = $conn->prepare("SELECT start, status FROM log WHERE start >= ?");
$stmt->bind_param('s', $curDate);
$stmt->execute();
$stmt->bind_result($start, $status);
$stmt->close();
//second stmt
$stmt = $conn->prepare("SELECT time FROM params");
$stmt->bind_result($time);
$stmt->execute();
$stmt->close();
/* fetch values and echo for testing */
while ($stmt->fetch()) {
echo $start;
echo $status;
echo $time;
}
Any help is appreciated.
In general, there is nothing special in running two or dozen prepared statements - you just have run them one by one. Thus there is no "best way" at all.
In your particular case the best way is to get rid of prepared statements:
$time = $conn->query("SELECT time FROM params")->fetch_object()->time;
$res = $conn->query("SELECT start, status FROM log WHERE start >= CURDATE()");
while($row = $res->fetch_object())
{
echo $row->start;
echo $row->status;
echo $time;
}

How should I write PHP $_POST variable in a mysql_query function?

Simple question. How do i make the query work? I know you can't directly use $_POST in a query. But i do not know how to get this to work.
$sql = 'SELECT * FROM users WHERE `password` = $_POST[password] AND `username` = $_POST[username]';
$result = mysqli_query($link, $sql);
if (!$result) {
echo "DB Error, could not query the database\n";
echo 'MySQL Error: ' . mysqli_error($link);
exit;
I have also tried using the mysqli_real_escape_string like this :
$username_sql = mysqli_real_escape_string($link, $_POST['username']);
$password_sql = mysqli_real_escape_string($link, $_POST['password']);
This did not work as planned. As it did still not work.
Thanks,
Mike
use '' with string comparison of MySQL
$username_sql = mysqli_real_escape_string($link, $_POST['username']);
$password_sql = mysqli_real_escape_string($link, $_POST['password']);
$sql = "SELECT * FROM users
WHERE `password` = '$username_sql' AND `username` = '$password_sql'";
Use prepared statements to avoid sql injection and syntax errors with commas .
$sql = 'SELECT * FROM users WHERE `password` = ? AND `username` = ?';
$stmt = mysqli_stmt_init($link);
mysqli_stmt_prepare($stmt, $sql);
mysqli_stmt_bind_param($stmt, "ss", $_POST['password'], $_POST['username']);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
while($row = mysqli_fetch_assoc($result){
echo $row['username'] .'<br>';
}
I think it is necessary to add at least one example of prepared statements, just to show that it is not more difficult and it makes your application safer (SQL-injection).
$stmt = $mysqli->prepare('SELECT * FROM users WHERE `password` = ? AND `username` = ?');
$stmt->bind_param("ss", $_POST[password], $_POST[username]);
$stmt->execute();
$stmt->bind_result($result);
$stmt->fetch();
// read the result...
$stmt->close();
Be aware that passwords should not be stored plain text, instead one should use the functions password_hash() and password_verify().
You answered your question yourself.
mysqli_real_escape_string() is the way to go.
$sql = 'SELECT * FROM users WHERE `password` = "' . mysqli_real_escape_string($_POST[password]) . '" AND `username` = "' . mysqli_real_escape_string($_POST[username]') . '"';

PHP prepare and execute

I was using the following code to execute the queries in the database:
$sql = "SELECT * FROM cc_topchoices WHERE location='$location' ORDER BY position asc";
$result = mysqli_query($conn, $sql);
I have read that this way to make the queries is not secure so I want to use the statements prepare() and execute() in php
Now my code looks like this:
$sql = "SELECT * FROM cc_topchoices WHERE location=:location ORDER BY position asc";
$stmt = $conn->prepare($sql);
$stmt->execute(array(":location" => $location));
$result = mysqli_query($conn, $stmt);
But this give me this error:
Fatal error: Call to a member function execute() on boolean
Any idea?
EDIT
Now my code looks like this:
// Create connection
$conn = new PDO("mysql:host=$servername;dbname=$dbname", "$username", "$password");
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->exec("set names utf8"); //BECAUSE I NEED TO WORK WITH CHINESE LANGUAGE
$sql = "SELECT * FROM cc_topchoices WHERE location=? ORDER BY position asc";
$stmt = $conn->prepare($sql);
$stmt->bindParam(':location', $location);
$stmt->execute(array($location));
$result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
if ($result > 0) {
// output data of each row
while($row = $stmt->fetch()) {
echo "<li><div><a href='". $row["rest_url"] ."'><img src='images/top_choices/". $row["image"] ."' alt='". $row["alt_desc"]. "' /></a></div></li>";
}
} else {
echo "0 results";
}
is working :) just need to know if this is a good and secure practice
PDO supports named parameters. MySQLi does not. $stmt is false to show you that the SQL you tried to prepare is syntactically malformed. Use ? instead of :location. Check the MySQLi manual for the correct way to use MySQLi. Or, alternately, switch to PDO.
Use below code to fetch records instead of mysqli_query when using pdo statements if your query returns single row.
$result = $stmt->fetch(PDO::FETCH_ASSOC);
echo $result['db_column'];
And if return multiple rows:
$stmt->setFetchMode(PDO::FETCH_ASSOC);
while ($result = $stmt->fetch()) {
echo $result['db_column'];
}
And one more thing, always put your prepared statement in try{}..catch{} block.
It will work for you.

Prepared statements and mysqli_query / mysqli_num_rows?

I am trying to find out how to make my code work with prepared statements. I understood the entire process up to where I commented my code. What do I have to do in order to integrate num_rows and the mysqli_query part properly?
function login_check() {
global $connection;
$name = $_POST['name'];
$password = $_POST['password'];
$query = "SELECT id FROM members WHERE name = $name AND password = $password";
$stmt = $connection->prepare($query);
$stmt->bind_param('ss', $name, $password);
$stmt->execute();
$stmt->close();
// $result = mysqli_query($connection, $query);
// $rows = mysqli_num_rows($result);
if($rows > 0){
header('location:../../success.php');
exit;
}
else {
header('location:../../failed.php');
exit;
}
}
What I tried:
$result = mysqli_query($connection, $stmt);
$rows = mysqli_num_rows($result);
Change
$query = "SELECT id FROM members WHERE name = $name AND password = $password";
to
$query = "SELECT `id` FROM `members` WHERE `name` = ? AND `password` = ?";
Adding backticks around table and columns prevents mysql reserved words error.
Remove $stmt->close();
if( $stmt->num_rows > 0 ) {
$stmt->close();
header('location:../../success.php');
exit();
} else {
$stmt->close();
header('location:../../failed.php');
exit();
}
Adding $stmt->close() inside if statement before header is best practice in this case.
Becasue adding it before if statement would result in $stmt->num_rows always returning 0; Adding it after the if statment won't work because exit() would prefent it from executing.
From the documentation:
Closes a prepared statement. mysqli_stmt_close() also deallocates the statement handle. If the current statement has pending or unread results, this function cancels them so that the next query can be executed.

How can I properly use a PDO object for a parameterized SELECT query

I've tried following the PHP.net instructions for doing SELECT queries but I am not sure the best way to go about doing this.
I would like to use a parameterized SELECT query, if possible, to return the ID in a table where the name field matches the parameter. This should return one ID because it will be unique.
I would then like to use that ID for an INSERT into another table, so I will need to determine if it was successful or not.
I also read that you can prepare the queries for reuse but I wasn't sure how this helps.
You select data like this:
$db = new PDO("...");
$statement = $db->prepare("select id from some_table where name = :name");
$statement->execute(array(':name' => "Jimbo"));
$row = $statement->fetch(); // Use fetchAll() if you want all results, or just iterate over the statement, since it implements Iterator
You insert in the same way:
$statement = $db->prepare("insert into some_other_table (some_id) values (:some_id)");
$statement->execute(array(':some_id' => $row['id']));
I recommend that you configure PDO to throw exceptions upon error. You would then get a PDOException if any of the queries fail - No need to check explicitly. To turn on exceptions, call this just after you've created the $db object:
$db = new PDO("...");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
I've been working with PDO lately and the answer above is completely right, but I just wanted to document that the following works as well.
$nametosearch = "Tobias";
$conn = new PDO("server", "username", "password");
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sth = $conn->prepare("SELECT `id` from `tablename` WHERE `name` = :name");
$sth->bindParam(':name', $nametosearch);
// Or sth->bindParam(':name', $_POST['namefromform']); depending on application
$sth->execute();
You can use the bindParam or bindValue methods to help prepare your statement.
It makes things more clear on first sight instead of doing $check->execute(array(':name' => $name)); Especially if you are binding multiple values/variables.
Check the clear, easy to read example below:
$q = $db->prepare("SELECT id FROM table WHERE forename = :forename and surname = :surname LIMIT 1");
$q->bindValue(':forename', 'Joe');
$q->bindValue(':surname', 'Bloggs');
$q->execute();
if ($q->rowCount() > 0){
$check = $q->fetch(PDO::FETCH_ASSOC);
$row_id = $check['id'];
// do something
}
If you are expecting multiple rows remove the LIMIT 1 and change the fetch method into fetchAll:
$q = $db->prepare("SELECT id FROM table WHERE forename = :forename and surname = :surname");// removed limit 1
$q->bindValue(':forename', 'Joe');
$q->bindValue(':surname', 'Bloggs');
$q->execute();
if ($q->rowCount() > 0){
$check = $q->fetchAll(PDO::FETCH_ASSOC);
//$check will now hold an array of returned rows.
//let's say we need the second result, i.e. index of 1
$row_id = $check[1]['id'];
// do something
}
A litle bit complete answer is here with all ready for use:
$sql = "SELECT `username` FROM `users` WHERE `id` = :id";
$q = $dbh->prepare($sql);
$q->execute(array(':id' => "4"));
$done= $q->fetch();
echo $done[0];
Here $dbh is PDO db connecter, and based on id from table users we've get the username using fetch();
I hope this help someone, Enjoy!
Method 1:USE PDO query method
$stmt = $db->query('SELECT id FROM Employee where name ="'.$name.'"');
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
Getting Row Count
$stmt = $db->query('SELECT id FROM Employee where name ="'.$name.'"');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';
Method 2: Statements With Parameters
$stmt = $db->prepare("SELECT id FROM Employee WHERE name=?");
$stmt->execute(array($name));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
Method 3:Bind parameters
$stmt = $db->prepare("SELECT id FROM Employee WHERE name=?");
$stmt->bindValue(1, $name, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
**bind with named parameters**
$stmt = $db->prepare("SELECT id FROM Employee WHERE name=:name");
$stmt->bindValue(':name', $name, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
or
$stmt = $db->prepare("SELECT id FROM Employee WHERE name=:name");
$stmt->execute(array(':name' => $name));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
Want to know more look at this link
if you are using inline coding in single page and not using oops than go with this full example, it will sure help
//connect to the db
$dbh = new PDO('mysql:host=localhost;dbname=mydb', dbuser, dbpw);
//build the query
$query="SELECT field1, field2
FROM ubertable
WHERE field1 > 6969";
//execute the query
$data = $dbh->query($query);
//convert result resource to array
$result = $data->fetchAll(PDO::FETCH_ASSOC);
//view the entire array (for testing)
print_r($result);
//display array elements
foreach($result as $output) {
echo output[field1] . " " . output[field1] . "<br />";
}

Categories