I'm trying to make the following code work but I can't reach the execute() line.
$mysqli = $this->ConnectLowPrivileges();
echo 'Connected<br>';
$stmt = $mysqli->prepare("SELECT `name`, `lastname` FROM `tblStudents` WHERE `idStudent`=?");
echo 'Prepared and binding parameters<br>';
$stmt->bind_param('i', 2 );
echo 'Ready to execute<br>'
if ($stmt->execute()){
echo 'Executing..';
}
} else {
echo 'Error executing!';
}
mysqli_close($mysqli);
The output that I get is:
Connected
Prepared and binding parameters
So the problem should be at line 5, but checking the manual of bind_param() I can't find any syntax error there.
When binding parameters you need to pass a variable that is used as a reference:
$var = 1;
$stmt->bind_param('i', $var);
See the manual: http://php.net/manual/en/mysqli-stmt.bind-param.php
Note that $var doesn't actually have to be defined to bind it. The following is perfectly valid:
$stmt->bind_param('i', $var);
foreach ($array as $element)
{
$var = $element['foo'];
$stmt->execute();
}
here it is just a simple explaination
declare a variable to be bind
$var="email";
$mysqli = $this->ConnectLowPrivileges();
echo 'Connected<br>';
$var="email";
$stmt = $mysqli->prepare("SELECT name, lastname FROM tablename WHERE idStudent=?" LIMIT=1);
echo 'Prepared and binding parameters<br>';
$stmt->bindparam(1,$var);
Your actual problem is not at line 5 but rather at line 1.
You are trying to use unusable driver.
While PDO does exactly what you want.
$sql = "SELECT `name`, `lastname` FROM `tblStudents` WHERE `idStudent`=?"
$stm = $this->pdo->prepare($sql);
$stm->execute(array(2));
return $stm->fetch();
After all the years passed since this answer has been written, a new PHP feature emerged, called "argument unpacking". So, since version 5.6 you can pass a value into bind_param:
$stmt->bind_param('i', ...[2]);
But still you have a trouble with getting your data back out of a prepared statement :)
Related
Some people recommends calling close() on a prepared statement when I am done with the result of a query.
I often reuse the same variable name for the prepared statement, so I was wondering if overriding the variable automatically calls close() on the prepared statement ?
Example of how I currently do it (The SQL is made up for the examples):
// Fetch the requested user
$stmt = $mysqli->prepare("SELECT * FROM user WHERE id = ?");
$stmt->bind_param("i", $_GET['userid']);
$stmt->execute();
$user = $stmt->get_result()->fetch_assoc();
// Fetch all posts associated with the user
$stmt = $mysqli->prepare("SELECT * FROM posts WHERE user_id = ?");
$stmt->bind_param("i", $user['id']);
$stmt->execute();
$result = $stmt->get_result();
$posts = array();
while ($row = $result->fetch_assoc()) {
$posts[] = $row;
}
Should I call $stmt->close(); between fetching the user and fetching the posts or is it done when I override $stmt by calling $stmt = $mysqli->prepare(...); ?
Yes, most of the time, because PHP will try to clean up objects which have no reference as soon as possible. That means that once you overwrite it, there will be no more references to the old object and PHP will clean it up. Part of cleaning up mysqli_stmt object involves closing the statement.
But the reason why some people recommend calling $stmt->close() explicitely is to avoid errors such as this:
mysqli_sql_exception: Commands out of sync; you can't run this command now in ...
This error happens when you have not fetched all results from MySQL and you try to create a new statement by calling prepare or query. MySQL will not let you execute anything else until you fetch all remaining rows. This is usually achieved with get_result() or store_result(). If you always fetch the results in their entirety then you really don't need to worry much about when exactly the statement gets closed. Let PHP take care of it for you.
The best course of action is to avoid using mysqli functions directly. You should write some simple function which will encapsulate all the mysqli functionality so that you never have to worry about this low-level stuff. A sample function could look like this:
function safeQuery(\mysqli $db, string $sql, array $params = []): ?array {
$stmt = $db->prepare($sql);
if ($params) {
$stmt->bind_param(str_repeat("s", count($params)), ...$params);
}
$stmt->execute();
if ($result = $stmt->get_result()) {
return $result->fetch_all(MYSQLI_BOTH);
}
return null;
}
$result = safeQuery($mysqli, 'SELECT * FROM user WHERE id = ?', [$_GET['userid']]);
if ($result) {
$user = $result[0];
$posts = safeQuery($mysqli, 'SELECT * FROM posts WHERE user_id = ?', [$user['id']]);
foreach ($posts as $post) {
}
}
I got an error when I prepare my $query.
Here are the lines :
$query="INSERT INTO bm(title,season) VALUES(:title, :season)";
$stmt = $mysqli->prepare($query);
//$stmt->bind_param("ss", $title, $season);
$stmt->execute(array(':title' => $title, ':season' => $season));
I put the line with bind_param in //
I saw on others that could solve but error became roughly the same :
Fatal error: Call to a member function bind_param() on a non-object
So, I thought of my query but it's so simple I can't see anymore clearly. It's driving me nuts. :-/ I also tested the var $titleand $season with an echo just before the $query line to be sure, like this :
echo $title." et ".$season;
but nothing is wrong, values are ok. These are strings var. Any help would be very appreciated. Thanks.
Here is the complete code :
<?php
include("connexion.php");
// Get vars from previous form
//$id="";
$title = isset($_POST['title']) ? $_POST['title'] : "";
$season = isset($_POST['season']) ? $_POST['season'] : "";
// Testing vars
if (empty($titre) && empty($saison))
{
echo '<font color="red">Must be filled...</font>';
}
// Vars ok : could be inserted in "bm" table
else
{
// Protect - inject SQL
$title=$mysqli->real_escape_string(strip_tags($title));
$season=$mysqli->real_escape_string(strip_tags($season));
// Test
echo $title." et ".$season;
// Insert method
$query="INSERT INTO bm(title,season) VALUES(:title, :season)";
$stmt = $mysqli->prepare($query);
$stmt->bind_param("ss", $title, $season);
$stmt->execute(array(':title' => $title, ':season' => $season));
// Insert ok ?
if ($stmt) {
echo "Insert ok.";
}
else {
echo "Insert failed !";
}
}
//Close connexion
$mysqli->close();
?>
Try to change your database call as follows:
$query="INSERT INTO bm(title,season) VALUES(?, ?)";
$stmt = $mysqli->prepare($query);
//could be false if prepared statemant is somehow wrong
if ($stmt === false){
echo "Insert failed !";
}
else{
//bind the params to the variables
$stmt->bind_param("ss", $title, $season);
//no parameters allowed for execute method according to the doc
$success = $stmt->execute();
//check for $success if true/false
}
Why not use the most common used queing to fetch data from the database? The most commonly used is by using while loop for fetching data from the database right? I think that your approach(based on your code) perfectly works if you are using sqlsrv, but mysql and mysqli has almost the same syntax unlike from sqlsrv wherein it uses params to pass data, just my opinion :D
If you reference the documentation on PHP MYSQLI (http://php.net/manual/en/mysqli.prepare.php) you will notice that FALSE is returned when an error occurs in the prepare.
mysqli_prepare() returns a statement object or FALSE if an error occurred.
Instead of the call being from a mysqli_stmt object, it is from a FALSE boolean.
My assumption would be that the error occurs in your connection string if you are passing in proper variables. More code would be needed to troubleshoot further.
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 am trying to use prepared statements but having trouble getting it to successfully run.
here is my code:
function addAlbum($album){
$connection = mysqli_connect(HOST,USER,PASS,DATABASE);
/*$sql = 'INSERT INTO `'.TABLE_ALBUMS.'` (albumName) VALUES ("'.$album.'")';
$result = mysqli_query($connection,$sql);*/
$stmt = $dbh->prepare('INSERT INTO `'.TABLE_ALBUMS.'` (albumName) VALUES ("'.$album.'")');
$stmt->bindParam(':albumName', $album);
$result = $stmt->execute();
if($result){
header("Location: index.php?success");
} else {
header("Location: index.php?fail");
}
}
i have ran this in firefox with errors on and this is what i get:
Fatal error: Call to undefined method
mysqli_stmt::bindParam() in
/Applications/MAMP/htdocs/PHPproject/includes/functions.inc.php
on line 16
could any one please tell me where i am going wrong?
many thanks
First argument for bind should be the type of variable:
$stmt->bind_param("s", $album);
Also you should check the return value of execute() and not the $stmt:
$result = $stmt->execute();
if($result){
echo "yes";
}
else {
echo "no";
}
Also I'd say that it's not a good ideea to prepare the statement each time you insert something. Prepared statements should be class variables or if you're not in oop, global variables, so you don't prepare the statement each time you call the function. Just write a function init() that will prepare all the statements that you'll use.
All the examples I see using mysqli_fetch_object use mysql_query(), I cannot get it to work with prepared statements. Does anyone know what is wrong with this code snippet, as fetch_object returns null.
$sql = "select 1 from dual";
printf("preparing %s\n", $sql);
$stmt = $link->prepare($sql);
printf("prepare statement %s\n", is_null($stmt) ? "is null" : "created");
$rc = $stmt->execute();
printf("num rows is %d\n", $stmt->num_rows);
$result = $stmt->result_metadata();
printf("result_metadata %s\n", is_null($result) ? "is null" : "exists");
$rc = $result->fetch_object();
printf("fetch object returns %s\n", is_null($rc) ? "NULL" : $rc);
$stmt->close();
The output is:
preparing select 1 from dual
prepare statement created
num rows is 0
result_metadata exists
fetch object returns NULL
This is the code I use to create an object from a prepared statement.
It could perhaps be used in a subclass of mysqli?
$query = "SELECT * FROM category WHERE id = ?";
$stmt = $this->_db->prepare($query);
$value = 1;
$stmt->bind_param("i", $value);
$stmt->execute();
// bind results to named array
$meta = $stmt->result_metadata();
$fields = $meta->fetch_fields();
foreach($fields as $field) {
$result[$field->name] = "";
$resultArray[$field->name] = &$result[$field->name];
}
call_user_func_array(array($stmt, 'bind_result'), $resultArray);
// create object of results and array of objects
while($stmt->fetch()) {
$resultObject = new stdClass();
foreach ($resultArray as $key => $value) {
$resultObject->$key = $value;
}
$rows[] = $resultObject;
}
$stmt->close();
MySql Native Driver extension (mysqlnd), has the get_result method:
$stmt->execute();
$obj = $stmt->get_result()->fetch_object();
I don't believe the interface works like that.
Going by the documentation and examples (http://www.php.net/manual/en/mysqli.prepare.php) it seems that $stmt->execute() does not return a resultset, but a boolean indicating success / failure (http://www.php.net/manual/en/mysqli-stmt.execute.php). To actually get the result, you need to bind variables to the resultset (aftere the execute call) using $stmt->bind_result (http://www.php.net/manual/en/mysqli-stmt.bind-result.php).
After you did all that, you can do repeated calls to $stmt->fetch() () to fill the bound variables with the column values from the current row. I don't see any mention of $stmt->fetch_object() nor do I see how that interface could work with a variable binding scheme like described.
So this is the story for "normal" result fetching from mysqli prepared statments.
In your code, there is something that I suspect is an error, or at least I am not sure you intended to do this.
You line:
$result = $stmt->result_metadata();
assignes the resultset metadata, which is itself represented as a resultset, to the $result variable. According to the doc (http://www.php.net/manual/en/mysqli-stmt.result-metadata.php) you can only use a subset of the methods on these 'special' kinds of resultsets, and fetch_object() is not one of them (at least it is not explicitly listed).
Perhaps it is a bug that fetch_object() is not implemented for these metadata resultsets, perhaps you should file a bug at bugs.mysql.com about that.