I would like to see an example of how to call using bind_result vs. get_result and what would be the purpose of using one over the other.
Also the pro and cons of using each.
What is the limitation of using either and is there a difference.
Although both methods work with * queries, when bind_result() is used, the columns are usually listed explicitly in the query, so one can consult the list when assigning returned values in bind_result(), because the order of variables must strictly match the structure of the returned row.
Example 1 for $query1 using bind_result()
$query1 = 'SELECT id, first_name, last_name, username FROM `table` WHERE id = ?';
$id = 5;
$stmt = $mysqli->prepare($query1);
/*
Binds variables to prepared statement
i corresponding variable has type integer
d corresponding variable has type double
s corresponding variable has type string
b corresponding variable is a blob and will be sent in packets
*/
$stmt->bind_param('i',$id);
/* execute query */
$stmt->execute();
/* Store the result (to get properties) */
$stmt->store_result();
/* Get the number of rows */
$num_of_rows = $stmt->num_rows;
/* Bind the result to variables */
$stmt->bind_result($id, $first_name, $last_name, $username);
while ($stmt->fetch()) {
echo 'ID: '.$id.'<br>';
echo 'First Name: '.$first_name.'<br>';
echo 'Last Name: '.$last_name.'<br>';
echo 'Username: '.$username.'<br><br>';
}
Example 2 for $query2 using get_result()
$query2 = 'SELECT * FROM `table` WHERE id = ?';
$id = 5;
$stmt = $mysqli->prepare($query2);
/*
Binds variables to prepared statement
i corresponding variable has type integer
d corresponding variable has type double
s corresponding variable has type string
b corresponding variable is a blob and will be sent in packets
*/
$stmt->bind_param('i',$id);
/* execute query */
$stmt->execute();
/* Get the result */
$result = $stmt->get_result();
/* Get the number of rows */
$num_of_rows = $result->num_rows;
while ($row = $result->fetch_assoc()) {
echo 'ID: '.$row['id'].'<br>';
echo 'First Name: '.$row['first_name'].'<br>';
echo 'Last Name: '.$row['last_name'].'<br>';
echo 'Username: '.$row['username'].'<br><br>';
}
bind_result()
Pros:
Works with outdated PHP versions
Returns separate variables
Cons:
All variables have to be listed manually
Requires more code to return the row as array
The code must be updated every time when the table structure is changed
get_result()
Pros:
Returns associative/enumerated array or object, automatically filled with data from the returned row
Allows fetch_all() method to return all returned rows at once
Cons:
requires MySQL native driver (mysqlnd)
Examples you can find on the respective manual pages, get_result() and bind_result().
While pros and cons are quite simple:
get_result() is the only sane way to handle results
yet it could be not always available on some outdated and unsupported PHP version
In a modern web application the data is never displayed right off the query. The data has to be collected first and only then output has to be started. Or even if you don't follow the best practices, there are cases when the data has to be returned, not printed right away.
Keeping that in mind let's see how to write a code that returns the selected data as a nested array of associative arrays using both methods.
bind_result()
$query1 = 'SELECT id, first_name, last_name, username FROM `table` WHERE id = ?';
$stmt = $mysqli->prepare($query1);
$stmt->bind_param('s',$id);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($id, $first_name, $last_name, $username);
$rows = [];
while ($stmt->fetch()) {
$rows[] = [
'id' => $id,
'first_name' => $first_name,
'last_name' => $last_name,
'username' => $username,
];
}
and remember to edit this code every time a column is added or removed from the table.
get_result()
$query2 = 'SELECT * FROM `table` WHERE id = ?';
$stmt = $mysqli->prepare($query2);
$stmt->bind_param('s', $id);
$stmt->execute();
$rows = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
and this code remains the same when the table structure is changed.
And there's more.
In case you decide to automate the boring routine of preparing/binding/executing into a neat function that would be called like this
$query = 'SELECT * FROM `table` WHERE id = ?';
$rows = prepared_select($query, [$id])->fetch_all(MYSQLI_ASSOC);
with get_result() it will be quite a plausible task, a matter of just a few lines. But with bind_param() it will will be a tedious quest.
That's why I call the bind_result() method "ugly".
get_result() is only available in PHP by installing the MySQL native driver (mysqlnd). In some environments, it may not be possible or desirable to install mysqlnd.
Notwithstanding, you can still use mysqli to do SELECT * queries, and get the results with the field names - although it is slightly more complicated than using get_result(), and involves using PHP's call_user_func_array() function. See example at How to use bind_result() instead of get_result() in php which does a simple SELECT * query and outputs the results (with the column names) to an HTML table.
Main difference I've noticed is that bind_result() gives you error 2014, when you try to code nested $stmt inside other $stmt, that is being fetched (without mysqli::store_result() ):
Prepare failed: (2014) Commands out of sync; you can't run this command now
Example:
Function used in main code.
function GetUserName($id)
{
global $conn;
$sql = "SELECT name FROM users WHERE id = ?";
if ($stmt = $conn->prepare($sql)) {
$stmt->bind_param('i', $id);
$stmt->execute();
$stmt->bind_result($name);
while ($stmt->fetch()) {
return $name;
}
$stmt->close();
} else {
echo "Prepare failed: (" . $conn->errno . ") " . $conn->error;
}
}
Main code.
$sql = "SELECT from_id, to_id, content
FROM `direct_message`
WHERE `to_id` = ?";
if ($stmt = $conn->prepare($sql)) {
$stmt->bind_param('i', $myID);
/* execute statement */
$stmt->execute();
/* bind result variables */
$stmt->bind_result($from, $to, $text);
/* fetch values */
while ($stmt->fetch()) {
echo "<li>";
echo "<p>Message from: ".GetUserName($from)."</p>";
echo "<p>Message content: ".$text."</p>";
echo "</li>";
}
/* close statement */
$stmt->close();
} else {
echo "Prepare failed: (" . $conn->errno . ") " . $conn->error;
}
Related
I am using mysqli to get the row but it is not giving me row, and there is no error in query.
$query="select * from members where useremail='$user_email' and password='$password'";
$result=$db->query($query);
$row = $db->fetch_array($result);
echo $row['id'];
My query Function
function query($query){
$result=mysqli_query($this->conn, $query);
if(!$result){
echo $this->err_msg = mysqli_error($this->conn);
return false;
}else{
return $result;
}
}
My fetch_array Function
function fetch_array($result){
return mysqli_fetch_array($result);
}
How can i get Row using mysqli ?
Change your original code to reflect bound parameters using mysqli, this is more secure and should work
$query="select * from members where useremail='$user_email' and password='$password'";
$result=$db->query($query);
$row = $db->fetch_array($result);
echo $row['id'];
to bound parameters using mysqli prepared statements
$query="select id from members where useremail=? and password=?"; // Don't use select *, select each column, ? are placeholders for your bind variables
$stmt = $connection->prepare($query);
if($stmt){
$stmt->bind_param("ss",$user_email,$password); // Bind in your variables, s is for string, i is for integers
$stmt->execute();
$stmt->bind_result($id); // bind the result to these variables, in the order you select
$stmt->store_result(); // Store if large result set, can throw error if server is setup to not handle more than x data
$stmt->fetch();
$stmt->close();
}
echo $id; // this would be same as $row['id'], $id now holds for example 5.
If you select multiple things, such as "SELECT id,name FROM...", then when you bind_result(..), just bind them n there. $stmt->bind_result($id,$name);
now $id and $name hold the column data for that row matching your query. If there would be multiple rows matching, instead of $stmt->fetch() you'd do
while($stmt->fetch()){ // just like while($row = $result->fetch_assoc()){}
echo $id;
echo $name
}
I would like to see an example of how to call using bind_result vs. get_result and what would be the purpose of using one over the other.
Also the pro and cons of using each.
What is the limitation of using either and is there a difference.
Although both methods work with * queries, when bind_result() is used, the columns are usually listed explicitly in the query, so one can consult the list when assigning returned values in bind_result(), because the order of variables must strictly match the structure of the returned row.
Example 1 for $query1 using bind_result()
$query1 = 'SELECT id, first_name, last_name, username FROM `table` WHERE id = ?';
$id = 5;
$stmt = $mysqli->prepare($query1);
/*
Binds variables to prepared statement
i corresponding variable has type integer
d corresponding variable has type double
s corresponding variable has type string
b corresponding variable is a blob and will be sent in packets
*/
$stmt->bind_param('i',$id);
/* execute query */
$stmt->execute();
/* Store the result (to get properties) */
$stmt->store_result();
/* Get the number of rows */
$num_of_rows = $stmt->num_rows;
/* Bind the result to variables */
$stmt->bind_result($id, $first_name, $last_name, $username);
while ($stmt->fetch()) {
echo 'ID: '.$id.'<br>';
echo 'First Name: '.$first_name.'<br>';
echo 'Last Name: '.$last_name.'<br>';
echo 'Username: '.$username.'<br><br>';
}
Example 2 for $query2 using get_result()
$query2 = 'SELECT * FROM `table` WHERE id = ?';
$id = 5;
$stmt = $mysqli->prepare($query2);
/*
Binds variables to prepared statement
i corresponding variable has type integer
d corresponding variable has type double
s corresponding variable has type string
b corresponding variable is a blob and will be sent in packets
*/
$stmt->bind_param('i',$id);
/* execute query */
$stmt->execute();
/* Get the result */
$result = $stmt->get_result();
/* Get the number of rows */
$num_of_rows = $result->num_rows;
while ($row = $result->fetch_assoc()) {
echo 'ID: '.$row['id'].'<br>';
echo 'First Name: '.$row['first_name'].'<br>';
echo 'Last Name: '.$row['last_name'].'<br>';
echo 'Username: '.$row['username'].'<br><br>';
}
bind_result()
Pros:
Works with outdated PHP versions
Returns separate variables
Cons:
All variables have to be listed manually
Requires more code to return the row as array
The code must be updated every time when the table structure is changed
get_result()
Pros:
Returns associative/enumerated array or object, automatically filled with data from the returned row
Allows fetch_all() method to return all returned rows at once
Cons:
requires MySQL native driver (mysqlnd)
Examples you can find on the respective manual pages, get_result() and bind_result().
While pros and cons are quite simple:
get_result() is the only sane way to handle results
yet it could be not always available on some outdated and unsupported PHP version
In a modern web application the data is never displayed right off the query. The data has to be collected first and only then output has to be started. Or even if you don't follow the best practices, there are cases when the data has to be returned, not printed right away.
Keeping that in mind let's see how to write a code that returns the selected data as a nested array of associative arrays using both methods.
bind_result()
$query1 = 'SELECT id, first_name, last_name, username FROM `table` WHERE id = ?';
$stmt = $mysqli->prepare($query1);
$stmt->bind_param('s',$id);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($id, $first_name, $last_name, $username);
$rows = [];
while ($stmt->fetch()) {
$rows[] = [
'id' => $id,
'first_name' => $first_name,
'last_name' => $last_name,
'username' => $username,
];
}
and remember to edit this code every time a column is added or removed from the table.
get_result()
$query2 = 'SELECT * FROM `table` WHERE id = ?';
$stmt = $mysqli->prepare($query2);
$stmt->bind_param('s', $id);
$stmt->execute();
$rows = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
and this code remains the same when the table structure is changed.
And there's more.
In case you decide to automate the boring routine of preparing/binding/executing into a neat function that would be called like this
$query = 'SELECT * FROM `table` WHERE id = ?';
$rows = prepared_select($query, [$id])->fetch_all(MYSQLI_ASSOC);
with get_result() it will be quite a plausible task, a matter of just a few lines. But with bind_param() it will will be a tedious quest.
That's why I call the bind_result() method "ugly".
get_result() is only available in PHP by installing the MySQL native driver (mysqlnd). In some environments, it may not be possible or desirable to install mysqlnd.
Notwithstanding, you can still use mysqli to do SELECT * queries, and get the results with the field names - although it is slightly more complicated than using get_result(), and involves using PHP's call_user_func_array() function. See example at How to use bind_result() instead of get_result() in php which does a simple SELECT * query and outputs the results (with the column names) to an HTML table.
Main difference I've noticed is that bind_result() gives you error 2014, when you try to code nested $stmt inside other $stmt, that is being fetched (without mysqli::store_result() ):
Prepare failed: (2014) Commands out of sync; you can't run this command now
Example:
Function used in main code.
function GetUserName($id)
{
global $conn;
$sql = "SELECT name FROM users WHERE id = ?";
if ($stmt = $conn->prepare($sql)) {
$stmt->bind_param('i', $id);
$stmt->execute();
$stmt->bind_result($name);
while ($stmt->fetch()) {
return $name;
}
$stmt->close();
} else {
echo "Prepare failed: (" . $conn->errno . ") " . $conn->error;
}
}
Main code.
$sql = "SELECT from_id, to_id, content
FROM `direct_message`
WHERE `to_id` = ?";
if ($stmt = $conn->prepare($sql)) {
$stmt->bind_param('i', $myID);
/* execute statement */
$stmt->execute();
/* bind result variables */
$stmt->bind_result($from, $to, $text);
/* fetch values */
while ($stmt->fetch()) {
echo "<li>";
echo "<p>Message from: ".GetUserName($from)."</p>";
echo "<p>Message content: ".$text."</p>";
echo "</li>";
}
/* close statement */
$stmt->close();
} else {
echo "Prepare failed: (" . $conn->errno . ") " . $conn->error;
}
I'm trying to patch over to params from standard mysqli. I can´t wrap my head around how to target the columns i want with the new way to get results from db. lets say i have table with id, firstname, lastname, and about.
$query = mysqli_query($con, $sqlstmt);
while($row = mysqli_fetch_assoc($query){
$row['firstname'];
$row['about'];
}
this is easily done however when i try to use params,execute etc i cant really wrap it.
$stmt = mysqli_prepare($connect, "SELECT * FROM medlemmar WHERE firstname=?");
mysqli_stmt_bind_param($stmt, 's', $firstname,);
mysqli_stmt_execute($stmt);
I don't know how to fetch results from specific columns when using second choice and how to make an array of it etc.
In normal case i would just do
$array[]= $row['firstname']
When you use prepared statements, it takes one extra step to get the mysqli_result resource from the statement. Then you can use it like you used the mysqli_result you got from mysqli_query().
$stmt = $mysqli->prepare("SELECT name, userid FROM somewhere");
$stmt->execute();
$result = $stmt->get_result();
while($row = $result->fetch_assoc()) {
$row['firstname'];
$row['about'];
}
This usage requires mysqlnd, which is enabled by default in PHP 5.4+.
If you don't have mysqlnd, you have to bind results, like shown in the answer from #joaofgf.
It's worthwhile to upgrade to mysqlnd for its extra features and better performance.
you should use the associative bind stmt_bind_assoc()
example:
$stmt = $mysqli->prepare("SELECT name, userid FROM somewhere");
$stmt->execute();
$row = array();
stmt_bind_assoc($stmt, $row);
// loop through all result rows
while ($stmt->fetch()) {
print_r($row);
}
source: http://www.php.net/manual/en/mysqli-stmt.fetch.php
I am new to using prepared statements in mysql with php. I need some help creating a prepared statement to retrieve columns.
I need to get information from different columns. Currently for a test file, I use the completely unsecure SQL statement:
$qry = "SELECT * FROM mytable where userid='{$_GET['userid']}' AND category='{$_GET['category']}'ORDER BY id DESC"
$result = mysql_query($qry) or die(mysql_error());
Can someone help me create a secure mysql statement using input from url parameters (as above) that is prepared?
BONUS: Prepared statements are suppose to increase speed as well. Will it increase overall speed if I only use a prepared statement three or four times on a page?
Here's an example using mysqli (object-syntax - fairly easy to translate to function syntax if you desire):
$db = new mysqli("host","user","pw","database");
$stmt = $db->prepare("SELECT * FROM mytable where userid=? AND category=? ORDER BY id DESC");
$stmt->bind_param('ii', intval($_GET['userid']), intval($_GET['category']));
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($column1, $column2, $column3);
while($stmt->fetch())
{
echo "col1=$column1, col2=$column2, col3=$column3 \n";
}
$stmt->close();
Also, if you want an easy way to grab associative arrays (for use with SELECT *) instead of having to specify exactly what variables to bind to, here's a handy function:
function stmt_bind_assoc (&$stmt, &$out) {
$data = mysqli_stmt_result_metadata($stmt);
$fields = array();
$out = array();
$fields[0] = $stmt;
$count = 1;
while($field = mysqli_fetch_field($data)) {
$fields[$count] = &$out[$field->name];
$count++;
}
call_user_func_array(mysqli_stmt_bind_result, $fields);
}
To use it, just invoke it instead of calling bind_result:
$stmt->store_result();
$resultrow = array();
stmt_bind_assoc($stmt, $resultrow);
while($stmt->fetch())
{
print_r($resultrow);
}
You can write this instead:
$qry = "SELECT * FROM mytable where userid='";
$qry.= mysql_real_escape_string($_GET['userid'])."' AND category='";
$qry.= mysql_real_escape_string($_GET['category'])."' ORDER BY id DESC";
But to use prepared statements you better use a generic library, like PDO
<?php
/* Execute a prepared statement by passing an array of values */
$sth = $dbh->prepare('SELECT * FROM mytable where userid=? and category=?
order by id DESC');
$sth->execute(array($_GET['userid'],$_GET['category']));
//Consider a while and $sth->fetch() to fetch rows one by one
$allRows = $sth->fetchAll();
?>
Or, using mysqli
<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$category = $_GET['category'];
$userid = $_GET['userid'];
/* create a prepared statement */
if ($stmt = mysqli_prepare($link, 'SELECT col1, col2 FROM mytable where
userid=? and category=? order by id DESC')) {
/* bind parameters for markers */
/* Assumes userid is integer and category is string */
mysqli_stmt_bind_param($stmt, "is", $userid, $category);
/* execute query */
mysqli_stmt_execute($stmt);
/* bind result variables */
mysqli_stmt_bind_result($stmt, $col1, $col2);
/* fetch value */
mysqli_stmt_fetch($stmt);
/* Alternative, use a while:
while (mysqli_stmt_fetch($stmt)) {
// use $col1 and $col2
}
*/
/* use $col1 and $col2 */
echo "COL1: $col1 COL2: $col2\n";
/* close statement */
mysqli_stmt_close($stmt);
}
/* close connection */
mysqli_close($link);
?>
I agree with several other answers:
PHP's ext/mysql has no support for parameterized SQL statements.
Query parameters are considered more reliable in protecting against SQL injection issues.
mysql_real_escape_string() can also be effective if you use it correctly, but it's more verbose to code.
In some versions, international character sets have cases of characters that are not escaped properly, leaving subtle vulnerabilities. Using query parameters avoids these cases.
You should also note that you still have to be cautious about SQL injection even if you use query parameters, because parameters only take the place of literal values in SQL queries. If you build SQL queries dynamically and use PHP variables for the table name, column name, or any other part of SQL syntax, neither query parameters nor mysql_real_escape_string() help in this case. For example:
$query = "SELECT * FROM $the_table ORDER BY $some_column";
Regarding performance:
The performance benefit comes when you execute a prepared query multiple times with different parameter values. You avoid the overhead of parsing and preparing the query. But how often do you need to execute the same SQL query many times in the same PHP request?
Even when you can take advantage of this performance benefit, it is usually only a slight improvement compared to many other things you could do to address performance, like using opcode caching or data caching effectively.
There are even some cases where a prepared query harms performance. For example in the following case, the optimizer can't assume it can use an index for the search, because it must assume the parameter value might begin with a wildcard:
SELECT * FROM mytable WHERE textfield LIKE ?
Security with MySQL in PHP (or any other language for that matter) is a largely discussed issue. Here are a few places for you to pick up some great tips:
http://webmaster-forums.code-head.com/showthread.php?t=939
http://www.sitepoint.com/article/php-security-blunders/
http://dev.mysql.com/tech-resources/articles/guide-to-php-security.html
http://www.scribd.com/doc/17638718/Module-11-PHP-MySQL-Database-Security-16
The two most major items in my opinion are:
SQL Injection: Be sure to escape all of your query variables with PHP's mysql_real_escape_string() function (or something similar).
Input Validation: Never trust the user's input. See this for a tutorial on how to properly sanitize and validation your inputs.
If you're going to use mysqli - which seems the best solution to me - I highly recommend downloading a copy of the codesense_mysqli class.
It's a neat little class that wraps up and hides most of the cruft that accumulates when using raw mysqli such that using prepared statements only takes a line or two extra over the old mysql/php interface
Quite late, but this might help someone:
/**
* Execute query method. Executes a user defined query
*
* #param string $query the query statement
* #param array(Indexed) $col_vars the column variables to replace parameters. The count value should equal the number of supplied parameters
*
* Note: Use parameters in the query then supply the respective replacement variables in the second method parameter. e.g. 'SELECT COUNT(*) as count FROM foo WHERE bar = ?'
*
* #return array
*/
function read_sql($query, $col_vars=null) {
$conn = new mysqli('hostname', 'username', 'user_pass', 'dbname');
$types = $variables = array();
if (isset($col_vars)) {
for ($x=0; $x<count($col_vars); $x++) {
switch (gettype($col_vars[$x])) {
case 'integer':
array_push($types, 'i');
break;
case 'double':
array_push($types, 'd');
break;
default:
array_push($types, 's');
}
array_push($variables, $col_vars[$x]);
}
$types = implode('', $types);
$sql = $conn->prepare($query);
$sql -> bind_param($types, ...$variables);
$sql -> execute();
$results = $sql -> get_result();
$sql -> close();
}else {
$results = $conn->query($query) or die('Error: '.$conn->error);
}
if ($results -> num_rows > 0) {
while ($row = $results->fetch_assoc()) {
$result[] = $row;
}
return $result;
}else {
return null;
}
}
You can then invoke the function like so:
read_sql('SELECT * FROM mytable where userid = ? AND category = ? ORDER BY id DESC', array($_GET['userid'], $_GET['category']));
My site is rather extensive, and I just recently made the switch to PHP5 (call me a late bloomer).
All of my MySQL query's before were built as such:
"SELECT * FROM tablename WHERE field1 = 'value' && field2 = 'value2'";
This made it very easy, simple and friendly.
I am now trying to make the switch to mysqli for obvious security reasons, and I am having a hard time figuring out how to implement the same SELECT * FROM queries when the bind_param requires specific arguments.
Is this statement a thing of the past?
If it is, how do I handle a query with tons of columns involved? Do I really need to type them all out every time?
I could be wrong, but for your question I get the feeling that bind_param() isn't really the problem here. You always need to define some conditions, be it directly in the query string itself, of using bind_param() to set the ? placeholders. That's not really an issue.
The problem I had using MySQLi SELECT * queries is the bind_result() part. That's where it gets interesting. I came across this post from Jeffrey Way: http://jeff-way.com/2009/05/27/tricky-prepared-statements/(This link is no longer active). The script basically loops through the results and returns them as an array — no need to know how many columns there are, and you can still use prepared statements.
In this case it would look something like this:
$stmt = $mysqli->prepare(
'SELECT * FROM tablename WHERE field1 = ? AND field2 = ?');
$stmt->bind_param('ss', $value, $value2);
$stmt->execute();
Then use the snippet from the site:
$meta = $stmt->result_metadata();
while ($field = $meta->fetch_field()) {
$parameters[] = &$row[$field->name];
}
call_user_func_array(array($stmt, 'bind_result'), $parameters);
while ($stmt->fetch()) {
foreach($row as $key => $val) {
$x[$key] = $val;
}
$results[] = $x;
}
And $results now contains all the info from SELECT *. So far I found this to be an ideal solution.
"SELECT * FROM tablename WHERE field1 = 'value' && field2 = 'value2'";
becomes
"SELECT * FROM tablename WHERE field1 = ? && field2 = ?";
which is passed to the $mysqli::prepare:
$stmt = $mysqli->prepare(
"SELECT * FROM tablename WHERE field1 = ? && field2 = ?");
$stmt->bind_param( "ss", $value, $value2);
// "ss' is a format string, each "s" means string
$stmt->execute();
$stmt->bind_result($col1, $col2);
// then fetch and close the statement
OP comments:
so if i have 5 parameters, i could potentially have "sssis" or something (depending on the types of inputs?)
Right, one type specifier per ? parameter in the prepared statement, all of them positional (first specifier applies to first ? which is replaced by first actual parameter (which is the second parameter to bind_param)).
While you are switching, switch to PDO instead of mysqli, It helps you write database agnositc code and have better features for prepared statements.
http://www.php.net/pdo
Bindparam for PDO:
http://se.php.net/manual/en/pdostatement.bindparam.php
$sth = $dbh->prepare("SELECT * FROM tablename WHERE field1 = :value1 && field2 = :value2");
$sth->bindParam(':value1', 'foo');
$sth->bindParam(':value2', 'bar');
$sth->execute();
or:
$sth = $dbh->prepare("SELECT * FROM tablename WHERE field1 = ? && field2 = ?");
$sth->bindParam(1, 'foo');
$sth->bindParam(2, 'bar');
$sth->execute();
or execute with the parameters as an array:
$sth = $dbh->prepare("SELECT * FROM tablename WHERE field1 = :value1 && field2 = :value2");
$sth->execute(array(':value1' => 'foo' , ':value2' => 'bar'));
It will be easier for you if you would like your application to be able to run on different databases in the future.
I also think you should invest some time in using some of the classes from Zend Framwework whilst working with PDO. Check out their Zend_Db and more specifically [Zend_Db_Factory][2]. You do not have to use all of the framework or convert your application to the MVC pattern, but using the framework and reading up on it is time well spent.
Is this statement a thing of the past?
Yes. Don't use SELECT *; it's a maintenance nightmare. There are tons of other threads on SO about why this construct is bad, and how avoiding it will help you write better queries.
See also:
What is the reason not to use select *?
Performance issue in using SELECT *?
Why is using '*' to build a view bad?
You can still use it (mysqli is just another way of communicating with the server, the SQL language itself is expanded, not changed). Prepared statements are safer, though - since you don't need to go through the trouble of properly escaping your values each time. You can leave them as they were, if you want to but the risk of sql piggybacking is reduced if you switch.
you can use get_result() on the statement.
http://php.net/manual/en/mysqli-stmt.get-result.php
I was looking for a nice and complete example of how to bind multiple query parameters dynamically to any SELECT, INSERT, UPDATE and DELETE query. Alec mentions in his answer a way of how to bind result, for me the get_result() after execute() function for SELECT queries works just fine, and am able to retrieve all the selected results into an array of associative arrays.
Anyway, I ended up creating a function where I am able to dynamically bind any amount of parameters to a parametrized query ( using call_user_func_array function) and obtain a result of the query execution. Below is the function with its documentation (please read before it before using - especially the $paremetersTypes - Type specification chars parameter is important to understand)
/**
* Prepares and executes a parametrized QUERY (SELECT, INSERT, UPDATE, DELETE)
*
* #param[in] $dbConnection mysqli database connection to be used for query execution
* #param[in] $dbQuery parametrized query to be bind parameters for and then execute
* #param[in] $isDMQ boolean value, should be set to TRUE for (DELETE, INSERT, UPDATE - Data manipulaiton queries), FALSE for SELECT queries
* #param[in] $paremetersTypes String representation for input parametrs' types as per http://php.net/manual/en/mysqli-stmt.bind-param.php
* #param[in] $errorOut A variable to be passed by reference where a string representation of an error will be present if a FAUILURE occurs
* #param[in] $arrayOfParemetersToBind Parameters to be bind to the parametrized query, parameters need to be specified in an array in the correct order
* #return array of feched records associative arrays for SELECT query on SUCCESS, TRUE for INSERT, UPDATE, DELETE queries on SUCCESS, on FAIL sets the error and returns NULL
*/
function ExecuteMySQLParametrizedQuery($dbConnection, $dbQuery, $isDMQ, $paremetersTypes, &$errorOut, $arrayOfParemetersToBind)
{
$stmt = $dbConnection->prepare($dbQuery);
$outValue = NULL;
if ($stmt === FALSE)
$errorOut = 'Failed to prepare statement for query: ' . $dbQuery;
else if ( call_user_func_array(array($stmt, "bind_param"), array_merge(array($paremetersTypes), $arrayOfParemetersToBind)) === FALSE)
$errorOut = 'Failed to bind required parameters to query: ' . $dbQuery . ' , parameters :' . json_encode($arrayOfParemetersToBind);
else if (!$stmt->execute())
$errorOut = "Failed to execute query [$dbQuery] , erorr:" . $stmt->error;
else
{
if ($isDMQ)
$outValue = TRUE;
else
{
$result = $stmt->get_result();
if ($result === FALSE)
$errorOut = 'Failed to obtain result from statement for query ' . $dbQuery;
else
$outValue = $result->fetch_all(MYSQLI_ASSOC);
}
}
$stmt->close();
return $outValue;
}
usage:
$param1 = "128989";
$param2 = "some passcode";
$insertQuery = "INSERT INTO Cards (Serial, UserPin) VALUES (?, ?)";
$rowsInserted = ExecuteMySQLParametrizedQuery($dbConnection, $insertQuery, TRUE, 'ss', $errorOut, array(&$param1, &$param2) ); // Make sure the parameters in an array are passed by reference
if ($rowsInserted === NULL)
echo 'error ' . $errorOut;
else
echo "successfully inserted row";
$selectQuery = "SELECT CardID FROM Cards WHERE Serial like ? AND UserPin like ?";
$arrayOfCardIDs = ExecuteMySQLParametrizedQuery($dbConnection, $selectQuery, FALSE, 'ss', $errorOut, array(&$param1, &$param2) ); // Make sure the parameters in an array are passed by reference
if ($arrayOfCardIDs === NULL)
echo 'error ' . $errorOut;
else
{
echo 'obtained result array of ' . count($arrayOfCardIDs) . 'selected rows';
if (count($arrayOfCardIDs) > 0)
echo 'obtained card id = ' . $arrayOfCardIDs[0]['CardID'];
}