I am very new to prepared statements.
This is my code:
<?php
$getImages=$db->prepare("SELECT * FROM header_image_arabic");
$getImages->bind_param('s', '$images');
$getImages->execute();
$getImages->bind_result($returned_images);
while($img=$returned_images->fetch_object()){
?>
This is the error:
Fatal error: Cannot pass parameter 2 by reference in C:\wamp\www\arabia\admin\includes\pan\imageHeader.php on line 22`
What does this error mean?
There are number of things wrong here.
'$images' is a string containing 7 characters. You want to pass the variable to bind_param, not a string.
$getImages->bind_param('s', $images);
Also, what exactly are you trying to bind to here? There are no placeholders (question marks) in your query. You can just use $db->query() here. You only need to "prepare" a query when you are filling in data.
$getImages = $db->query('SELECT * FROM header_image_arabic');
if($getImages === FALSE){
die($db->error);
}
while($img = $getImages->fetch_object()){
}
Another thing is the line: $getImages->bind_result($returned_images);. bind_result is used to bind to the fields in the query. You can't use that here, since you are doing SELECT *. (Also, fetch_object and bind_result cannot be used together. You need to use get_result (which only works with the mysqlnd driver) to be able to use fetch_object.)
So, if you wanted to use "prepared statements", it would look something like this:
$getImages = $db->prepare("SELECT image_id FROM header_image_arabic WHERE name = ?");
$getImages->bind_param('s', $images);
$getImages->execute();
$getImages->bind_result($returned_images);
while($getImages->fetch()){
// This will get updated each iteration
echo $returned_images;
}
Or like this (requires mysqlnd driver):
$getImages = $db->prepare("SELECT * FROM header_image_arabic WHERE name = ?");
$getImages->bind_param('s', $images);
$getImages->execute();
$result = $getImages->get_result();
while($img = $result->fetch_object()){
echo $img->image_id;
}
Related
I am writing a pretty basic piece of code to fetch one or (in most cases) multiple rows from a mysql database.
function getschema($mysqli){
$id = $_SESSION['user_id'];
$query = $mysqli->prepare("SELECT a.naam
FROM schemes AS a, aankoop AS b
WHERE b.aankoop_username_id = :userid && b.aankoop_schema_id = a.id");
$query->bind_param(':userid', $id, PDO::PARAM_INT);
$query->execute();
$result = $query->fetchAll();
echo ($result);
}
I get the user id from the session and pull the data with the query in the prepared statement.
This statement is correct. I tried it in phpmyadmin and it returns the correct values.
Now I want to use this function in my HTML like so...
<?php echo getschema($mysqli); ?>
But my code does not return a thing, it even messes up the layout of my html page where I want to show the code.
I think it probably is something with the fetchAll command. I also tried the PDO::Fetch_ASSOC but that did not work either.
In addition, I cannot see the php errors, even when they are enabled in the php.ini file.
Here's what's going on; you're mixing MySQL APIs/functions and those do not intermix.
Replace the :userid (PDO) bind in b.aankoop_username_id = :userid with a ? placeholder
b.aankoop_username_id = ?
Then this line:
$query->bind_param(':userid', $id, PDO::PARAM_INT);
Replace :userid by $id and remove , PDO::PARAM_INT but adding i
$query->bind_param("i", $id);
Sidenote: Make sure that column is int type. If not, use s instead of i.
Replace the line for fetchAll with the loop as outlined in AbraCadaver's answer.
You can't mix MySQL APIs/function, read the following on Stack:
Can I mix MySQL APIs in PHP?
Read up on mysqli with prepared statements and how it works:
http://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php
Checking for errors would have outlined the errors.
http://php.net/manual/en/mysqli.error.php
http://php.net/manual/en/function.error-reporting.php
Instead of echo ($result); do return $result; in your function.
Then to use it you have to loop over the array of rows and echo the column that you want:
foreach(getschema($mysqli) as $row) {
echo $row['naam'];
}
Or assign the function return to a variable and loop over that:
$rows = getschema($mysqli);
Sorry if this seems a really stupid question, but I'm struggling to get to grips with changing from Mysql to Mysqli and prepared statements.
So in mysql, I would have done this:
$q=('SELECT * FROM table WHERE field="'.$variable.'"');
$result = mysql_query($q);
I now know this is not good. So I now have the below:
$stmt = $mysqli->prepare('SELECT * FROM table WHERE field=? LIMIT 1');
$stmt->bind_param('s', $variable);
$stmt->execute();
Problem is that the query doesn't work. Say the ? is actually "tree". So the query becomes:
'SELECT * FROM table WHERE field=tree LIMIT 1'
If I tried to run that query in say phpmyadmin I get "Unknown column tree in where clause". Obviously if I put quotes around it then it works, hence the original query. So how can I get this to work if I can't use quotes, since then you are looking for the literal question mark?
For reference I am then using this code:
$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;
}
As I can't use get_result() which is very annoying. I have PHP version 5.4, and even the mysqlnd driver, but can't enable it as I'm on a VPS and my host says it might affect other sites on that server. Consequently what is actually just two lines in MySql is actually now something like 15 lines in the 'improved' mysqli. Great.
Any help would be appreciated!
This:
$stmt = $mysqli->prepare('SELECT * FROM table WHERE field=? LIMIT 1');
$stmt->bind_param('s', $variable);
is not equivalent to this:
SELECT * FROM table WHERE field=tree LIMIT 1
Prepared statement placeholders are not the same as copy and pasting in values. You are binding the value "tree" as a string here, the database will actually understand this. The ? is not simply being replaced by the bound value, the database understands the difference between your query structure with its placeholders and the values you're binding into them. Binding the parameter this way is equivalent to running:
SELECT * FROM table WHERE field='tree' LIMIT 1
Consequently what is actually just two lines in MySql is actually now something like 15 lines in the 'improved' mysqli. Great.
Mysqli is not intended to be used as is. It is but a building material for the higher level library. When used wisely, it can give you data in one line:
$data = $db->getAll('SELECT * FROM table WHERE field=?s', $variable);
(BTW, the same goes for the old mysql ext as well)
This yields proper results, but I would like to have the resulting row in an array, instead of binding individual variables to each field, so I can access fields like $row[0] and/or $row["name"].
$idToSearch = 2;
$conn = new mysqli("localhost", "username", "password", "db_people");
$statement = $conn->prepare("SELECT name, age from People where id = ?");
$statement->bind_param("i", $idToSearch);
$statement->execute();
$statement->bind_result($name, $age);
if($statement->fetch()) {
echo "The name is $name and the age is $age. ";
} else {
echo "No person found with that id.";
}
Saw an example about fetch_assoc(), but it used a mysqli_result class which I don't know hot to use and unprepared statements which I'd rather not use.
EDIT: To clarify, I'm fine with a solution whether it uses bind_result or not.
In order to use fetch_assoc you would need to use get_results which would force you to not use the bind which it seems you don't want to do. So I believe what you want to do is explained pretty well by user uramihsayibok in the php docs for the bind_result function, specifically here: http://php.net/manual/en/mysqli-stmt.bind-result.php#92505. They explain how to work around that in order get the results into an array.
I'm trying to switch to pdo and have enjoyed success with it but my latest function will not work. When I revert to mysqli, however, it is fine. I'm sure I'm missing something, but what??
not working PDO:
$db = db_pdo();
$query = $db->prepare("select * from locks_for_sale where type_3=':search'");
$query->bindParam(":search", $sub_items[3]);
$query->execute();
if (!$result=$query->fetch()) {
$print .= "<tr><td> </td><td><h3>No products currently available.</h3></td></tr>\n";
}
else {
other code
Please note:
function db_pdo is included.
$sub_items[3] is a string.
working mysqli:
$db = db_conn();
$sql = "select * from locks_for_sale where type_3='".$sub_items[3]."'";
$query = $db->query($sql);
if (!$query->fetch_assoc()) {
$print .= "<tr><td> </td><td><h3>No products currently available.</h3></td></tr>\n";
}
else {
other code
Again db_conn is included.
I know that the result of this query is returning 2 items but the pdo version shows !$result.
Thanks in advance.
Remove the quotes from the :search param:
$query = $db->prepare("select * from locks_for_sale where type_3=:search");
//--------------------------------------------------------------^^^^^^^^^^
If quoted, it would be treated as a literal string ':search', and you'll wind up with an error for binding an incorrect number of parameters.
If you are new to prepared statements, try not to think of them as the equivalent of placing variables into a SQL string as you would when concatenating or interpolating variables. Instead you are passing the parameter values directly into the database engine, which will in turn place them accordingly into the query. It becomes the RDBMS' responsibility to construct a valid statement with appropriate quoting.
Given your 00000 error code, that actually means the query succeeded. The problem is with your fetch logic:
if (!$query->fetch_assoc()) {
^--- remove
if the fetch succeeds, the call will return not-false, aka true. You then invert that with ! and turn it into a false, causing the other code to run.
try bindValue (http://www.php.net/manual/en/pdostatement.bindvalue.php)
<?php
/* Execute a prepared statement by binding PHP variables */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < :calories AND colour = :colour');
$sth->bindValue(':calories', $calories, PDO::PARAM_INT);
$sth->bindValue(':colour', $colour, PDO::PARAM_STR);
$sth->execute();
?>
See also:
What is the difference between bindParam and bindValue?
I created this code:
$statement = $db->prepare("SELECT * FROM phptech_contact");
$statement->execute();
$result = $statement->result_metadata();
$object = $result->fetch_object();
print_r( $object );
When I run it, it doesn't work. Can anybody tell me why it doesn't work?
I have 20 rows in this table so data should be returned.
From http://ch.php.net/manual/en/mysqli-stmt.result-metadata.php
Note: The result set returned by mysqli_stmt_result_metadata() contains only metadata. It does not contain any row results. The rows are obtained by using the statement handle with mysqli_stmt_fetch().
As long as you don't need this meta data you don't need to call this method.
$statement = $db->prepare("SELECT fld1, fld2 FROM phptech_contact");
$statement->execute();
$stmt->bind_result($fld1, $fld2);
while ($stmt->fetch()) {
echo "$fld1 and $fld2<br />";
}
But I really dislike the mysqli extension. PDO is much cooler ... ;-)
$db = new PDO('...');
$stmt = $db->prepare("SELECT fld1, fld2 FROM phptech_contact");
$stmt->execute();
while ($obj = $stmt->fetchObject()) {
// ...
}
or
$objs = stmt->fetchAll(PDO::FETCH_OBJ);
if you're trying to get the rows from the database, the function you need is mysqli_stmt::fetch(), not mysqli_stmt::fetch_metadata()
You're also missing a few steps. When using prepared statements, you must specify the fields you would like to return instead of using the star wildcard, and then use mysqli_stmt::bind_result() to specify which variables the database fields should be placed in.
If you're more familiar with the original MySQL extension, prepared statements have a different process to use. If your select statement has a parameter (eg., "WHERE value=?") prepared statements are definitely recommended, but for your simple query, mysqli:query() would be sufficient, and not very different from the process of mysql_query()
I believe the problem is that mysqli_stmt::result_metadata() returns a mysqli_result object without any of the actual results — it only holds metadata.
So what you want to do is use $result = $statement->bind_result(...) and then call $result->fetch() repeatedly to get the results.
One of the comments under the bind-result() article shows how to do this for a query like yours, where you don't necessarily know all of the columns being returned.