Let's say I have prepared a mysqli statement by doing $stmt = $connection->prepare("SELECT name, id, password_hash FROM person WHERE id = ?") and that I use this statement in a function:
function get_person_info($person_id) {
global $stmt;
$stmt->bind_param("s", $person_id);
$stmt->execute();
return $stmt->get_result()->fetch_array();
}
If I don't know how many times this function will be called, when should I close $stmt if I want optimal performance?
More specifically: what exactly happens when closing $stmt? I have read the documentation at php.net, but it was unclear to me whether or not I am supposed to close a statement if I plan on reusing it.
Don't close it. It will be closed at the script's end.
Related
If I do not close the stmt at the end of this code snippet:
$stmt = $mysqli->prepare("SELECT typeId FROM types WHERE name = 'author'");
$stmt->execute();
$stmt->bind_result($typeId);
$stmt->fetch();
(with this:)
$stmt->close();
Then the following prepared statement fails with error code 0 and no error:
$stmt = $mysqli->prepare("INSERT INTO typeTracker (reserved_id, typeId) VALUES (NULL, ?)");
$stmt->bind_param("i", $typeId);
Why? Is it because I called the bind_result and fetch functions in the first block of code? I don't typically have to close statements before preparing new ones.
Thanks.
If $stmt gets replaced or falls out of scope it gets destroyed. You can close it as a formality, but normally it gets taken care of anyway.
Calling close() frees up any associated resources immediately. If you don't do that you'll need to wait for the garbage collector to take care of it.
Using prepared statements to query the database in PHP is making me repeat a lot of code.
For instance, if I want to fetch a particular user from the database in my users.php file, I do it like this:
$sql = "SELECT * FROM users WHERE id=?";
// prepare sql statement
$stmt = $conn->prepare($sql);
// bind query parameters
$stmt->bind_param('i', $user_id);
// execute
$stmt->execute();
// get result object
$result = $stmt->get_result();
// fetch user from result as associative array
$user = $result->fetch_assoc();
To me, this is already a lot of code just to fetch a user. But no big deal, it is more secure so it is worth it.
The problem arises when I want to insert a post into the database in my post.php file. I do it like this:
$sql = "INSERT INTO posts SET user_id=?, title=?, body=?";
$stmt = $conn->prepare($sql);
$stmt->bind_param('iss', $user_id, $title, $body);
$result = $stmt->execute();
$stmt->close();
I am already seeing code repetition here. It means in my application if I want to query the database 100 times, I will have to repeat some lines of code such as the prepare(), bind_param(), execute() steps especially since the bind_param() parameters are always changing.
I have thought of refactoring this in one or two functions say in my database.php file so that I can just call the function passing the query and the parameters and have that function do all the prepare() and bind_param() and execute() functions.
Is this possible? If so is it good practice?
Thanks for any suggestions.
I've always used PDO statements, but for some reason I can't persuade the server guy to install PDO for php, but I do have MySQLi, I have no clue what I'm doing wrong, I do not get a connection error and I do not get a query error no matter how I try to output one. Here's what I'm doing.
include 'MySQLiConnect.php';
if($stmt = $mysqli->prepare("SELECT * FROM zipCodeTable WHERE zip_code = ?")){
$stmt->bind_param("s", '07110');
$stmt->execute();
$stmt->bind_result($resultsArray);
$stmt->fetch();
foreach($resultsArray as $columnData){
$matchingZipcode = $columnData['zip_code'];
$matchingTimezone = $columnData['time_zone'];
}
$stmt->close();
}
echo $matchingZipcode.', '.$matchingTimezone;
This is basically just to confirm a users zipcode, never used MySQLi prepared statements before, I tryed to do it straight from the manual, not sure what I'm doing wrong. Thank you for taking the time to read this.
You're trying to "bind" a literal string. You can't do this. You must bind a variable.
Change
$stmt->bind_param("s", '07110');
To
$string = '07110';
$stmt->bind_param("s", $string);
Also, when you bind a result you must provide a variable for each field returned.
For example:
$stmt->bind_result($zipCode, $timeZone);
This is slightly problematic when using SELECT *. You might be interested in checking out this comment for how you might want to go about it: http://www.php.net/manual/en/mysqli-stmt.bind-result.php#85470
I was researching about mysqli prepared statements and i have 2 questions about it.
As i was reading, i figure out that the order of execution of a prepared statement looks something like the following:
$sql = 'SELECT image_id, filename, caption FROM images WHERE image_id = ?';
// connect to the database
$conn = ....
$stmt = $conn->stmt_init();
$stmt->prepare($sql);
$stmt->bind_param('i', $id);
$stmt->execute();
$stmt->bind_result($image_id, $filename, $caption);
// optional: get total of records in the result set
$stmt->store_result();
$numRows = $stmt->num_rows;
// loop through the result set
while ($stmt->fetch()) {
// code goes here...
}
or
// fetch the result for one record
$stmt->fetch()
// free & close
$stmt->free_result();
$stmt->close;
$conn->close();
Here's my first question:
As i was reading, it also mentions the following:
If you don't bind the result to variables, use $row = $stmt->fetch(), and access each variable as $row['column_name']. So,
Are they any pros/cons using either of the 2 methods to loop the result set?
If there's no difference, then why bother binding the result using $stmt->bind_result in the first place? What's the point if i can use $row = $stmt->fetch() instead?
Here's my other question:
$stmt->free_result(); frees what exactly? the prepare() or the store_result() or else ?
$stmt->close; what am i closing exactly? the stmt_init() or the prepare() or else?
Hopefully your answers will make me understand better prepared statements so i can build something safe...
Thanks
$stmt->free_result() does pretty much what the name says: it frees the memory associated with a result.
$stmt->close closes the statement handle (the cursor actually), making it impossible to loop through the result set (again).
Although the manual states: 'You should always free your result with mysqli_free_result(), when your result object is not needed anymore', common practice is not to use free_result and close on a statement. When closed you cannot use the result set anymore, or reuse it and when php dies, memory is freed anyway.
I had a quick question with regard to prepared statements within PHP. I was previously using the mysql_query function to manipulate database data, but was told that for security issues I should consider using prepared statements. I have made the transition, but I have a few questions on how to detect whether a query has failed.
Below I have a piece of example code. The $con variable is a connection which is specific depending on the query I am attempting, in this case the connection would be to my database through an account with only select permissions.
$stmt = $con->stmt_init();
$stmt->prepare("SELECT COUNT(*) FROM users WHERE username=?");
$stmt->bind_param('s', $username);
$stmt->execute();
$stmt->bind_result($user_count);
$stmt->fetch();
$stmt->close();
I was wondering how one can detect failure within any of these steps? The most simple solution I can imagine would be simply to wrap the code using a try/catch.. but I was wondering if there is a more sophisticated way of doing this.
Thanks for reading my question.
To expand on Jared's comment, you could do the following:
$stmt->execute();
if( !$stmt->errorCode() ){
// do something with results
}else{
// do something with the error
}
$stmt->close();